代码迁移
This commit is contained in:
18
.babelrc
Normal file
18
.babelrc
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"presets": [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
"modules": false,
|
||||
"targets": {
|
||||
"browsers": ["> 1%", "last 2 versions", "ie >= 10"]
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
"plugins": [
|
||||
["@babel/plugin-proposal-decorators", { "legacy": true }],
|
||||
["@babel/plugin-proposal-class-properties", { "loose": false }],
|
||||
"@babel/plugin-syntax-dynamic-import"
|
||||
]
|
||||
}
|
||||
2
.browserslistrc
Normal file
2
.browserslistrc
Normal file
@ -0,0 +1,2 @@
|
||||
> 1%
|
||||
last 2 versions
|
||||
12
.editorconfig
Normal file
12
.editorconfig
Normal file
@ -0,0 +1,12 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
4
.eslintignore
Normal file
4
.eslintignore
Normal file
@ -0,0 +1,4 @@
|
||||
/lib/
|
||||
/web/
|
||||
/pack/
|
||||
|
||||
29
.eslintrc
Normal file
29
.eslintrc
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"root": true,
|
||||
"parser": "babel-eslint",
|
||||
"parserOptions": {
|
||||
"sourceType": "module"
|
||||
},
|
||||
"env": {
|
||||
"es6": true,
|
||||
"node": true,
|
||||
"browser": true
|
||||
},
|
||||
"plugins": ["prettier"],
|
||||
"extends": ["eslint:recommended", "plugin:prettier/recommended"],
|
||||
"globals": {
|
||||
"Cesium": false
|
||||
},
|
||||
"rules": {
|
||||
"global-require": 0,
|
||||
"indent": 0,
|
||||
"no-new": 0,
|
||||
"camelcase": 0,
|
||||
"padded-blocks": 0,
|
||||
"no-unused-vars": 0,
|
||||
"no-trailing-spaces": 0,
|
||||
"no-mixed-spaces-and-tabs": 0,
|
||||
"space-before-function-paren": [0, "always"],
|
||||
"no-multiple-empty-lines": 0
|
||||
}
|
||||
}
|
||||
131
.gitignore
vendored
131
.gitignore
vendored
@ -1,14 +1,123 @@
|
||||
# ---> VisualStudioCode
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
!.vscode/*.code-snippets
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# Local History for Visual Studio Code
|
||||
.history/
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Built Visual Studio Code Extensions
|
||||
*.vsix
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
*.idea
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
#static
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
.env.test
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
docs
|
||||
|
||||
# history
|
||||
.history
|
||||
|
||||
11
.markdownlintrc
Normal file
11
.markdownlintrc
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"default": true,
|
||||
"colors": true,
|
||||
"header-increment": false,
|
||||
"line-length": false,
|
||||
"no-trailing-punctuation": { "punctuation": ".,;:" },
|
||||
"no-duplicate-header": false,
|
||||
"no-inline-html": false,
|
||||
"no-hard-tabs": false,
|
||||
"whitespace": false
|
||||
}
|
||||
5
.prettierrc
Normal file
5
.prettierrc
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"eslintIntegration": true,
|
||||
"singleQuote": true,
|
||||
"semi": false
|
||||
}
|
||||
201
LICENSE
Normal file
201
LICENSE
Normal file
@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
203
LICENSE.MD
Normal file
203
LICENSE.MD
Normal file
@ -0,0 +1,203 @@
|
||||
Copyright (c) 2019-present Caven Chen
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright (c) 2019-present Caven Chen
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
26
README.en.md
Normal file
26
README.en.md
Normal file
@ -0,0 +1,26 @@
|
||||
# sdk4
|
||||
|
||||
#### Description
|
||||
4.0的sdk,兼容3.0,取消earthsdk的引用
|
||||
|
||||
#### Software Architecture
|
||||
Software architecture description
|
||||
|
||||
#### Installation
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### Instructions
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### Contribution
|
||||
|
||||
1. Fork the repository
|
||||
2. Create Feat_xxx branch
|
||||
3. Commit your code
|
||||
4. Create Pull Request
|
||||
28
README.md
28
README.md
@ -1,3 +1,27 @@
|
||||
# sdk4.0
|
||||
# sdk4
|
||||
|
||||
sdk4.0
|
||||
#### 介绍
|
||||
4.0的sdk,兼容3.0,取消earthsdk的引用
|
||||
|
||||
#### 软件架构
|
||||
软件架构说明
|
||||
|
||||
|
||||
#### 安装教程
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### 使用说明
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### 参与贡献
|
||||
|
||||
1. Fork 本仓库
|
||||
2. 新建 Feat_xxx 分支
|
||||
3. 提交代码
|
||||
4. 新建 Pull Request
|
||||
|
||||
40
ink-docstrap.json
Normal file
40
ink-docstrap.json
Normal file
@ -0,0 +1,40 @@
|
||||
{
|
||||
"tags": {
|
||||
"allowUnknownTags": true,
|
||||
"dictionaries": [
|
||||
"jsdoc"
|
||||
]
|
||||
},
|
||||
"source": {
|
||||
"include": [
|
||||
"./src"
|
||||
],
|
||||
"includePattern": ".+\\.js(doc|x)?$",
|
||||
"excludePattern": "(^|\\/|\\\\)_"
|
||||
},
|
||||
"templates": {
|
||||
"cleverLinks": false,
|
||||
"monospaceLinks": false,
|
||||
"default": {
|
||||
"outputSourceFiles": true
|
||||
},
|
||||
"systemName": "接口文档",
|
||||
"footer": "",
|
||||
"copyright": "",
|
||||
"navType": "vertical",
|
||||
"theme": "Cerulean",
|
||||
"linenums": true,
|
||||
"collapseSymbols": true,
|
||||
"inverseNav": true,
|
||||
"protocol": "html://",
|
||||
"methodHeadingReturns": true
|
||||
},
|
||||
"opts": {
|
||||
"destination": "./docs/docs/",
|
||||
"encoding": "utf8",
|
||||
"private": true,
|
||||
"recurse": true,
|
||||
"sort": false,
|
||||
"template": "./node_modules/ink-docstrap/template"
|
||||
}
|
||||
}
|
||||
17084
package-lock.json
generated
Normal file
17084
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
51
package.json
Normal file
51
package.json
Normal file
@ -0,0 +1,51 @@
|
||||
{
|
||||
"name": "YJEarth-JSSDK",
|
||||
"version": "2.5.0",
|
||||
"main": "build/YJEarth.min.js",
|
||||
"author": "",
|
||||
"license": "",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"dev": "yarn run clean && cross-env DZ=xj webpack --mode development ",
|
||||
"build": "yarn run clean && cross-env DZ=xj webpack --mode production --env.production ",
|
||||
"minami-3Ddoc": "jsdoc -c ink-docstrap.json ",
|
||||
"clean": "rimraf build/"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.4.0",
|
||||
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
||||
"@babel/plugin-proposal-decorators": "^7.25.9",
|
||||
"@babel/plugin-proposal-export-namespace-from": "^7.0.0",
|
||||
"@babel/plugin-proposal-function-sent": "^7.0.0",
|
||||
"@babel/plugin-proposal-json-strings": "^7.0.0",
|
||||
"@babel/plugin-proposal-numeric-separator": "^7.0.0",
|
||||
"@babel/plugin-proposal-throw-expressions": "^7.0.0",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
||||
"@babel/plugin-syntax-import-meta": "^7.0.0",
|
||||
"@babel/plugin-transform-runtime": "^7.4.0",
|
||||
"@babel/polyfill": "^7.4.0",
|
||||
"@babel/preset-env": "^7.4.2",
|
||||
"babel-eslint": "^10.0.1",
|
||||
"babel-loader": "^8.0.5",
|
||||
"copy-webpack-plugin": "^5.0.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"eslint": "^5.15.3",
|
||||
"eslint-config-prettier": "^4.1.0",
|
||||
"eslint-plugin-import": "^2.16.0",
|
||||
"eslint-plugin-node": "^8.0.1",
|
||||
"eslint-plugin-prettier": "^3.0.1",
|
||||
"eslint-plugin-promise": "^4.0.1",
|
||||
"ink-docstrap": "^1.3.2",
|
||||
"jsdoc": "^3.6.7",
|
||||
"prettier": "^1.16.4",
|
||||
"rimraf": "^2.6.3",
|
||||
"webpack": "^4.29.6",
|
||||
"webpack-cli": "^3.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"caniuse-lite": "^1.0.30001663",
|
||||
"child_process": "^1.0.2",
|
||||
"js-md5": "^0.7.3",
|
||||
"url-loader": "^4.1.1"
|
||||
}
|
||||
}
|
||||
204
src/BaseDialog/index.js
Normal file
204
src/BaseDialog/index.js
Normal file
@ -0,0 +1,204 @@
|
||||
class BaseDialog {
|
||||
constructor(container, options = {}) {
|
||||
this.container = container
|
||||
this.options = { ...options }
|
||||
this.options.ismove = true
|
||||
if(options.ismove === false) {
|
||||
this.options.ismove = options.ismove
|
||||
}
|
||||
this.closeCallBack = options.closeCallBack
|
||||
this._element = {}
|
||||
this._element_style = undefined
|
||||
}
|
||||
|
||||
async init() {
|
||||
|
||||
this.closeAll()
|
||||
DialogAll.push(this)
|
||||
this.isDestroy = false
|
||||
// body
|
||||
this._element.body = document.createElement('div');
|
||||
this._element.body.className = 'YJ-custom-base-dialog';
|
||||
this._element.body.style.top = this.options.top
|
||||
this._element.body.style.bottom = this.options.bottom
|
||||
this._element.body.style.left = this.options.left
|
||||
this._element.body.style.right = this.options.right
|
||||
this.container.appendChild(this._element.body)
|
||||
|
||||
//title
|
||||
this._element.title = document.createElement('div');
|
||||
this._element.title.className = 'title-box';
|
||||
this._element.title.innerHTML = `<span class="title">${(this.options.title || '')}</span>` + `<span class="close-box"><span class="close"></span><i>✕</i></span>`
|
||||
this._element.body.appendChild(this._element.title)
|
||||
|
||||
//content
|
||||
this._element.content = await document.createElement('div');
|
||||
this._element.content.className = 'content';
|
||||
this._element.body.appendChild(this._element.content)
|
||||
|
||||
// foot
|
||||
this._element.foot = await document.createElement('div');
|
||||
this._element.foot.className = 'foot';
|
||||
// this._element.foot.innerHTML = `
|
||||
// <button class="translational">平移</button>
|
||||
// <button class="resetting">重置</button>
|
||||
// <button class="delete">删除</button>
|
||||
// <button class="close">关闭</button>
|
||||
// `
|
||||
this._element.foot.innerHTML = `
|
||||
<button class="close">关闭</button>
|
||||
`
|
||||
this._element.body.appendChild(this._element.foot)
|
||||
|
||||
// 关闭
|
||||
let closeBtnsBox = this._element.body.getElementsByClassName('close-box')[0];
|
||||
closeBtnsBox.addEventListener('click', () => {
|
||||
this.close()
|
||||
});
|
||||
let closeBtns = this._element.body.getElementsByClassName('close');
|
||||
for (let i = 0; i < closeBtns.length; i++) {
|
||||
closeBtns[i].addEventListener('click', () => {
|
||||
this.close()
|
||||
});
|
||||
}
|
||||
|
||||
if(this.options.ismove) {
|
||||
this.moveDiv()
|
||||
}
|
||||
}
|
||||
|
||||
close() {
|
||||
let styles = document.getElementsByTagName("style")
|
||||
for (let i = styles.length - 1; i >= 0; i--) {
|
||||
if (styles[i].dataset) {
|
||||
if (styles[i].dataset.name === 'YJ_style_dialog') {
|
||||
document.getElementsByTagName('head')[0].removeChild(styles[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this._element.body && this._element.body.parentNode) {
|
||||
this.container.removeChild(this._element.body)
|
||||
}
|
||||
this._element.body = null
|
||||
this._element.title = null
|
||||
this._element.content = null
|
||||
this._element.foot = null
|
||||
this._element_style = null
|
||||
this.isDestroy = true
|
||||
if (this.closeCallBack) {
|
||||
this.closeCallBack()
|
||||
this.closeCallBack = null
|
||||
}
|
||||
}
|
||||
|
||||
closeAll() {
|
||||
for(let i=DialogAll.length-1;i>=0;i--) {
|
||||
DialogAll[i].close()
|
||||
DialogAll.splice(i, 1)
|
||||
}
|
||||
return
|
||||
let styles = document.getElementsByTagName("style")
|
||||
for (let i = styles.length - 1; i >= 0; i--) {
|
||||
if (styles[i].dataset) {
|
||||
if (styles[i].dataset.name === 'YJ_style_dialog') {
|
||||
document.getElementsByTagName('head')[0].removeChild(styles[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this._element_style) {
|
||||
this._element_style = null
|
||||
}
|
||||
let elms = this.container.getElementsByClassName('YJ-custom-base-dialog')
|
||||
for (let i = elms.length - 1; i >= 0; i--) {
|
||||
this.container.removeChild(elms[i])
|
||||
}
|
||||
this._element.body = null
|
||||
this._element.title = null
|
||||
this._element.content = null
|
||||
this._element.foot = null
|
||||
}
|
||||
|
||||
titleAppChild(node) {
|
||||
this._element.title.appendChild(node)
|
||||
}
|
||||
contentAppChild(node) {
|
||||
this._element.content.appendChild(node)
|
||||
}
|
||||
footAppChild(node, target) {
|
||||
if (target) {
|
||||
this._element.foot.insertBefore(node, target);
|
||||
}
|
||||
else {
|
||||
this._element.foot.prepend(node)
|
||||
}
|
||||
}
|
||||
|
||||
moveDiv() {
|
||||
let x = 0
|
||||
let y = 0
|
||||
let l = 0
|
||||
let t = 0
|
||||
let oClickDiv = this._element.body
|
||||
let _this = this
|
||||
oClickDiv.onmousedown = (e) => {
|
||||
if (e.toElement.className !== 'title-box') {
|
||||
return
|
||||
}
|
||||
// dialog的宽度、高度
|
||||
// let oMoveDivHeight = that.oMoveDiv.offsetHeight
|
||||
let oMoveDivHeight = this._element.body.offsetHeight
|
||||
// let oMoveDivWidth = that.oMoveDiv.offsetWidth
|
||||
let oMoveDivWidth = this._element.body.offsetWidth
|
||||
|
||||
x = e.clientX
|
||||
y = e.clientY
|
||||
|
||||
let leftPx = window.getComputedStyle(this._element.body).left
|
||||
let topPx = window.getComputedStyle(this._element.body).top
|
||||
|
||||
l = leftPx.substr(0, leftPx.indexOf('px')) * 1
|
||||
t = topPx.substr(0, topPx.indexOf('px')) * 1
|
||||
// 视口大小
|
||||
let windowHeight = document.documentElement.clientHeight
|
||||
let windowWidth = document.documentElement.clientWidth
|
||||
|
||||
//鼠标移动
|
||||
window.onmousemove = function (e) {
|
||||
e.preventDefault()
|
||||
//获取x和y
|
||||
let nx = e.clientX
|
||||
let ny = e.clientY
|
||||
//计算移动后的左偏移量和顶部的偏移量
|
||||
let leftPx = nx - (x - l)
|
||||
let topPx = ny - (y - t)
|
||||
if (leftPx < 0) {
|
||||
leftPx = 0
|
||||
} else if (leftPx + oMoveDivWidth > windowWidth) {
|
||||
leftPx = windowWidth - oMoveDivWidth
|
||||
}
|
||||
|
||||
if (topPx <= 0) {
|
||||
topPx = 0
|
||||
} else if (topPx + oMoveDivHeight > windowHeight) {
|
||||
topPx = windowHeight - oMoveDivHeight
|
||||
}
|
||||
_this._element.body.style.left = leftPx + 'px'
|
||||
_this._element.body.style.top = topPx + 'px'
|
||||
_this._element.body.style.bottom = 'unset'
|
||||
_this._element.body.style.right = 'unset'
|
||||
}
|
||||
}
|
||||
|
||||
//鼠标抬起事件
|
||||
document.onmouseup = function (e) {
|
||||
window.onmousemove = null
|
||||
}
|
||||
window.ondragend = function (e) {
|
||||
window.onmousemove = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let DialogAll = []
|
||||
|
||||
export default BaseDialog
|
||||
35
src/BaseDialog/rule.js
Normal file
35
src/BaseDialog/rule.js
Normal file
@ -0,0 +1,35 @@
|
||||
function check(elm, rule) {
|
||||
let input = elm.getElementsByTagName('input')[0]
|
||||
rules[rule.validator](input, rule.trigger, (s, error) => {
|
||||
if (s) {
|
||||
elm.className = 'input-box'
|
||||
let eElm = elm.getElementsByClassName('input-error-text')[0]
|
||||
if(eElm) {
|
||||
elm.removeChild(eElm)
|
||||
}
|
||||
}
|
||||
else {
|
||||
elm.className = 'input-box error'
|
||||
let e = rule.message || error
|
||||
let eElm = document.createElement('span');
|
||||
eElm.className = 'input-error-text'
|
||||
eElm.innerHTML = e
|
||||
elm.appendChild(eElm)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const rules = {
|
||||
notEmpty: (input, trigger, cd) => {
|
||||
input.addEventListener(trigger, ()=>{
|
||||
if (input.value) {
|
||||
cd(true)
|
||||
}
|
||||
else {
|
||||
cd(false, '不能为空!')
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export { check }
|
||||
905
src/Controller/index.js
Normal file
905
src/Controller/index.js
Normal file
@ -0,0 +1,905 @@
|
||||
/**
|
||||
* @description 平移旋转-改
|
||||
*/
|
||||
import MouseEvent from '../Event'
|
||||
class ControllerObject {
|
||||
constructor(sdk, options = {}) {
|
||||
this.sdk = sdk
|
||||
this.viwer = this.sdk.viewer
|
||||
this.options = options
|
||||
this.options.position = options.position || {}
|
||||
this.options.rotate = options.rotate || {}
|
||||
this.options.position.lng = this.options.position.lng || 0
|
||||
this.options.position.lat = this.options.position.lat || 0
|
||||
this.options.position.alt = this.options.position.alt || 0
|
||||
this.options.rotate.x = this.options.rotate.x || 0
|
||||
this.options.rotate.y = this.options.rotate.y || 0
|
||||
this.options.rotate.z = this.options.rotate.z || 0
|
||||
this.activeAxis
|
||||
this.activeCircle
|
||||
this.activeModelParam
|
||||
this.origin
|
||||
this.rayX
|
||||
this.rayY
|
||||
this.rayZ
|
||||
this.arrow = {}
|
||||
this.activeState
|
||||
this.coordArrows = []
|
||||
this.coordCircles = []
|
||||
|
||||
this.MapEvent = new MouseEvent(this.sdk)
|
||||
}
|
||||
|
||||
get position() {
|
||||
return this.options.position
|
||||
}
|
||||
set position(v) {
|
||||
this.options.position = v
|
||||
this.againArrow()
|
||||
this.againCircle()
|
||||
}
|
||||
|
||||
get rotate() {
|
||||
return this.options.rotate
|
||||
}
|
||||
set rotate(v) {
|
||||
this.options.rotate = v
|
||||
}
|
||||
|
||||
initParam() {
|
||||
this._params = {
|
||||
tx: this.options.position.lng, //模型中心X轴坐标(经度,单位:十进制度)
|
||||
ty: this.options.position.lat, //模型中心Y轴坐标(纬度,单位:十进制度)
|
||||
tz: this.options.position.alt, //模型中心Z轴坐标(高程,单位:米)
|
||||
rx: this.options.rotate.x, //X轴(经度)方向旋转角度(单位:度)
|
||||
ry: this.options.rotate.y, //Y轴(纬度)方向旋转角度(单位:度)
|
||||
rz: this.options.rotate.z //Z轴(高程)方向旋转角度(单位:度)
|
||||
}
|
||||
return { ...this.options.position, ...this.options.rotate }
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始编辑平移
|
||||
*/
|
||||
async editTranslational() {
|
||||
this.destroy()
|
||||
this.activeState = 'translational'
|
||||
this.MapEvent = new MouseEvent(this.sdk)
|
||||
// this.viwer.scene.camera.flyTo({
|
||||
// destination: new Cesium.Cartesian3.fromDegrees(104.17401, 30.63593, 1000),
|
||||
// orientation: {
|
||||
// pitch: Cesium.Math.toRadians(-35.0)
|
||||
// },
|
||||
// duration: 1
|
||||
// })
|
||||
/**
|
||||
* 创建一条射线
|
||||
*/
|
||||
let _this = this
|
||||
let param = this.initParam()
|
||||
let lng = param.lng
|
||||
let lat = param.lat
|
||||
let h = param.alt
|
||||
let viewer = this.viwer
|
||||
// let lon = 104.17401
|
||||
// let lat = 30.64593
|
||||
// let h = 0
|
||||
// 原点
|
||||
this.origin = Cesium.Cartesian3.fromDegrees(lng, lat, h)
|
||||
// 计算xyz轴方向
|
||||
const directionVectorX = Cesium.Cartesian3.normalize(Cesium.Cartesian3.subtract(this.origin, Cesium.Cartesian3.fromDegrees(lng - 0.001, lat, h), new Cesium.Cartesian3()), new Cesium.Cartesian3());
|
||||
const directionVectorY = Cesium.Cartesian3.normalize(Cesium.Cartesian3.subtract(this.origin, Cesium.Cartesian3.fromDegrees(lng, lat - 0.001, h), new Cesium.Cartesian3()), new Cesium.Cartesian3());
|
||||
const directionVectorZ = Cesium.Cartesian3.normalize(Cesium.Cartesian3.subtract(this.origin, Cesium.Cartesian3.fromDegrees(lng, lat, h - 1), new Cesium.Cartesian3()), new Cesium.Cartesian3());
|
||||
this.rayX = new Cesium.Ray(this.origin, directionVectorX)
|
||||
this.rayY = new Cesium.Ray(this.origin, directionVectorY)
|
||||
this.rayZ = new Cesium.Ray(this.origin, directionVectorZ)
|
||||
this.arrow.positionX = Cesium.Ray.getPoint(this.rayX, 0)
|
||||
this.arrow.positionY = Cesium.Ray.getPoint(this.rayY, 0)
|
||||
this.arrow.positionZ = Cesium.Ray.getPoint(this.rayZ, 0)
|
||||
|
||||
const matrix = Cesium.Transforms.eastNorthUpToFixedFrame(
|
||||
new Cesium.Cartesian3.fromDegrees(lng, lat, h)
|
||||
)
|
||||
// 获取相机的位置
|
||||
var cameraPosition = viewer.camera.position;
|
||||
// 计算相机与目标坐标之间的距离
|
||||
var distance = Cesium.Cartesian3.distance(cameraPosition, this.origin);
|
||||
let newRadius = distance / 15
|
||||
let scale = newRadius
|
||||
Cesium.Matrix4.multiplyByScale(matrix, new Cesium.Cartesian3(scale, scale, scale), matrix)
|
||||
let axisArrowX = this.createAxisArrow('model_edit_xAxis', [new Cesium.Cartesian3(0, 0.001, 0), new Cesium.Cartesian3(1, 0, 0)], matrix, Cesium.Color.RED)
|
||||
let axisArrowY = this.createAxisArrow('model_edit_yAxis', [new Cesium.Cartesian3(0, 0.001, 0), new Cesium.Cartesian3(0, 1, 0)], matrix, Cesium.Color.LIME)
|
||||
let axisArrowZ = this.createAxisArrow('model_edit_zAxis', [new Cesium.Cartesian3(0, 0.001, 0), new Cesium.Cartesian3(0, 0, 1)], matrix, Cesium.Color.BLUE)
|
||||
let positions = []
|
||||
let radius = 1
|
||||
// for (let i = 0; i <= 360; i += 3) {
|
||||
// const sin = Math.sin(Cesium.Math.toRadians(i))
|
||||
// const cos = Math.cos(Cesium.Math.toRadians(i))
|
||||
// const x = radius * cos
|
||||
// const y = radius * sin
|
||||
// positions.push(new Cesium.Cartesian3(x, y, 0))
|
||||
// }
|
||||
// console.log('positions', positions)
|
||||
// let axisCircular = this.createAxisCircular('model_edit_circular', positions, matrix)
|
||||
this.viwer.scene.primitives.add(axisArrowX)
|
||||
this.viwer.scene.primitives.add(axisArrowY)
|
||||
this.viwer.scene.primitives.add(axisArrowZ)
|
||||
// this.viwer.scene.primitives.add(axisCircular)
|
||||
|
||||
this.againArrow()
|
||||
|
||||
// this.viwer.entities.add({
|
||||
// id: "tool-position_plane_xy",
|
||||
// rectangle: {
|
||||
// coordinates: new Cesium.CallbackProperty(function () {
|
||||
// return Cesium.Rectangle.fromCartesianArray([positionX, positionY])
|
||||
// }, false),
|
||||
// material: Cesium.Color.YELLOW.withAlpha(0),
|
||||
// }
|
||||
// });
|
||||
|
||||
// 监听相机移动
|
||||
this.viwer.camera.percentageChanged = 0.001
|
||||
this.viwer.camera.changed.addEventListener(this.againArrow, { _that: this });
|
||||
|
||||
let coordinatesDiffer = { x: 0, y: 0 }
|
||||
let lastPickTime = 0;
|
||||
let timeoutEvent
|
||||
this.MapEvent.mouse_move((e, cartesian) => {
|
||||
moveEvent(e)
|
||||
})
|
||||
function moveEvent(movement) {
|
||||
if (!_this.activeAxis) {
|
||||
const now = Date.now();
|
||||
if (now - lastPickTime < 100) {
|
||||
clearTimeout(timeoutEvent)
|
||||
timeoutEvent = setTimeout(() => {
|
||||
moveEvent(movement)
|
||||
}, 100);
|
||||
return
|
||||
}
|
||||
clearTimeout(timeoutEvent)
|
||||
lastPickTime = now;
|
||||
let primitives = _this.coordArrows
|
||||
for (let i = 0; i < primitives.length; i++) {
|
||||
if (primitives[i].getGeometryInstanceAttributes) {
|
||||
switch (primitives[i]._name) {
|
||||
case 'model_edit_xAxis':
|
||||
primitives[i].appearance = new Cesium.PolylineMaterialAppearance({
|
||||
material: Cesium.Material.fromType(Cesium.Material.PolylineArrowType, {
|
||||
color: Cesium.Color.RED,
|
||||
}),
|
||||
translucent: true,
|
||||
renderState: {
|
||||
depthTest: {
|
||||
enabled: false,
|
||||
},
|
||||
depthMask: false,
|
||||
depthFunction: Cesium.DepthFunction.ALWAYS,
|
||||
},
|
||||
})
|
||||
break;
|
||||
case 'model_edit_yAxis':
|
||||
primitives[i].appearance = new Cesium.PolylineMaterialAppearance({
|
||||
material: Cesium.Material.fromType(Cesium.Material.PolylineArrowType, {
|
||||
color: Cesium.Color.LIME,
|
||||
}),
|
||||
translucent: true,
|
||||
renderState: {
|
||||
depthTest: {
|
||||
enabled: false,
|
||||
},
|
||||
depthMask: false,
|
||||
depthFunction: Cesium.DepthFunction.ALWAYS,
|
||||
},
|
||||
})
|
||||
break;
|
||||
case 'model_edit_zAxis':
|
||||
primitives[i].appearance = new Cesium.PolylineMaterialAppearance({
|
||||
material: Cesium.Material.fromType(Cesium.Material.PolylineArrowType, {
|
||||
color: Cesium.Color.BLUE,
|
||||
}),
|
||||
translucent: true,
|
||||
renderState: {
|
||||
depthTest: {
|
||||
enabled: false,
|
||||
},
|
||||
depthMask: false,
|
||||
depthFunction: Cesium.DepthFunction.ALWAYS,
|
||||
},
|
||||
})
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let pickedObjectArray = _this.viwer.scene.drillPick(movement.endPosition, 10);
|
||||
for (let i = pickedObjectArray.length - 1; i >= 0; i--) {
|
||||
let pick = pickedObjectArray[i]
|
||||
if (pick && pick.primitive && pick.id) {
|
||||
switch (pick.primitive._name) {
|
||||
case 'model_edit_xAxis':
|
||||
case 'model_edit_yAxis':
|
||||
case 'model_edit_zAxis':
|
||||
pick.primitive.appearance = new Cesium.PolylineMaterialAppearance({
|
||||
material: Cesium.Material.fromType(Cesium.Material.PolylineArrowType, {
|
||||
color: Cesium.Color.YELLOW,
|
||||
}),
|
||||
translucent: true,
|
||||
renderState: {
|
||||
depthTest: {
|
||||
enabled: false,
|
||||
},
|
||||
depthMask: false,
|
||||
depthFunction: Cesium.DepthFunction.ALWAYS,
|
||||
},
|
||||
})
|
||||
return
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
let y = movement.startPosition.y - movement.endPosition.y //负数往下
|
||||
|
||||
let endPosition = { x: movement.endPosition.x - coordinatesDiffer.x, y: movement.endPosition.y - coordinatesDiffer.y }
|
||||
let ray = viewer.camera.getPickRay(endPosition);//获取一条射线
|
||||
let position = viewer.scene.globe.pick(ray, viewer.scene);
|
||||
let finalPosition = new Cesium.Cartesian3();
|
||||
let matrix4 = Cesium.Transforms.eastNorthUpToFixedFrame(viewer.camera.position);
|
||||
Cesium.Matrix4.inverse(matrix4, matrix4);
|
||||
Cesium.Matrix4.multiplyByPoint(matrix4, position, finalPosition);
|
||||
Cesium.Cartesian3.normalize(finalPosition, finalPosition);
|
||||
let param = _this.initParam()
|
||||
let pitch = 90 + Cesium.Math.toDegrees(Math.asin(finalPosition.z))
|
||||
let camera_cartographic = Cesium.Cartographic.fromCartesian(viewer.camera.position);
|
||||
let a = camera_cartographic.height
|
||||
let b = _this.activeModelParam.alt
|
||||
// let d = Cesium.Cartesian3.distance(viewer.camera.position, position);
|
||||
let d = a / Math.cos(Cesium.Math.toRadians(pitch))
|
||||
let geodesic = new Cesium.EllipsoidGeodesic(Cesium.Cartographic.fromCartesian(position), Cesium.Cartographic.fromCartesian(viewer.camera.position))
|
||||
|
||||
position = Cesium.Ray.getPoint(ray, d * (1 - (b / a)))
|
||||
let cartographic = Cesium.Cartographic.fromCartesian(position);
|
||||
let lng = Cesium.Math.toDegrees(cartographic.longitude); // 经度
|
||||
let lat = Cesium.Math.toDegrees(cartographic.latitude); // 纬度
|
||||
let m
|
||||
switch (_this.activeAxis._name) {
|
||||
case 'model_edit_xAxis':
|
||||
_this._params.tx = lng
|
||||
_this._params.ty = _this.activeModelParam.lat
|
||||
_this._params.tz = b
|
||||
|
||||
_this.origin = Cesium.Cartesian3.fromDegrees(param.lng, param.lat, param.alt)
|
||||
// 计算xyz轴方向
|
||||
const directionVectorX = Cesium.Cartesian3.normalize(Cesium.Cartesian3.subtract(_this.origin, Cesium.Cartesian3.fromDegrees(param.lng - 0.001, param.lat, param.alt), new Cesium.Cartesian3()), new Cesium.Cartesian3());
|
||||
const directionVectorY = Cesium.Cartesian3.normalize(Cesium.Cartesian3.subtract(_this.origin, Cesium.Cartesian3.fromDegrees(param.lng, param.lat - 0.001, param.alt), new Cesium.Cartesian3()), new Cesium.Cartesian3());
|
||||
const directionVectorZ = Cesium.Cartesian3.normalize(Cesium.Cartesian3.subtract(_this.origin, Cesium.Cartesian3.fromDegrees(param.lng, param.lat, param.alt - 1), new Cesium.Cartesian3()), new Cesium.Cartesian3());
|
||||
_this.rayX = new Cesium.Ray(_this.origin, directionVectorX)
|
||||
_this.rayY = new Cesium.Ray(_this.origin, directionVectorY)
|
||||
_this.rayZ = new Cesium.Ray(_this.origin, directionVectorZ)
|
||||
break
|
||||
case 'model_edit_yAxis':
|
||||
_this._params.tx = _this.activeModelParam.lng
|
||||
_this._params.ty = lat
|
||||
_this._params.tz = b
|
||||
_this.origin = Cesium.Cartesian3.fromDegrees(param.lng, param.lat, param.alt)
|
||||
// 计算xyz轴方向
|
||||
const directionVectorX2 = Cesium.Cartesian3.normalize(Cesium.Cartesian3.subtract(_this.origin, Cesium.Cartesian3.fromDegrees(param.lng - 0.001, param.lat, param.alt), new Cesium.Cartesian3()), new Cesium.Cartesian3());
|
||||
const directionVectorY2 = Cesium.Cartesian3.normalize(Cesium.Cartesian3.subtract(_this.origin, Cesium.Cartesian3.fromDegrees(param.lng, param.lat - 0.001, param.alt), new Cesium.Cartesian3()), new Cesium.Cartesian3());
|
||||
const directionVectorZ2 = Cesium.Cartesian3.normalize(Cesium.Cartesian3.subtract(_this.origin, Cesium.Cartesian3.fromDegrees(param.lng, param.lat, param.alt - 1), new Cesium.Cartesian3()), new Cesium.Cartesian3());
|
||||
_this.rayX = new Cesium.Ray(_this.origin, directionVectorX2)
|
||||
_this.rayY = new Cesium.Ray(_this.origin, directionVectorY2)
|
||||
_this.rayZ = new Cesium.Ray(_this.origin, directionVectorZ2)
|
||||
break
|
||||
case 'model_edit_zAxis':
|
||||
_this.activeModelParam.alt += (Cesium.Cartesian3.distance(viewer.camera.position, Cesium.Cartesian3.fromDegrees(_this.options.position.lng, _this.options.position.lat, _this.options.position.alt)) / 4300) * y * 3
|
||||
_this._params.tx = _this.activeModelParam.lng
|
||||
_this._params.ty = _this.activeModelParam.lat
|
||||
_this._params.tz = _this.activeModelParam.alt
|
||||
_this.origin = Cesium.Cartesian3.fromDegrees(param.lng, param.lat, _this.activeModelParam.alt)
|
||||
// 计算xyz轴方向
|
||||
const directionVectorX3 = Cesium.Cartesian3.normalize(Cesium.Cartesian3.subtract(_this.origin, Cesium.Cartesian3.fromDegrees(param.lng - 0.001, param.lat, _this.activeModelParam.alt), new Cesium.Cartesian3()), new Cesium.Cartesian3());
|
||||
const directionVectorY3 = Cesium.Cartesian3.normalize(Cesium.Cartesian3.subtract(_this.origin, Cesium.Cartesian3.fromDegrees(param.lng, param.lat - 0.001, _this.activeModelParam.alt), new Cesium.Cartesian3()), new Cesium.Cartesian3());
|
||||
const directionVectorZ3 = Cesium.Cartesian3.normalize(Cesium.Cartesian3.subtract(_this.origin, Cesium.Cartesian3.fromDegrees(param.lng, param.lat, _this.activeModelParam.alt - 1), new Cesium.Cartesian3()), new Cesium.Cartesian3());
|
||||
_this.rayX = new Cesium.Ray(_this.origin, directionVectorX3)
|
||||
_this.rayY = new Cesium.Ray(_this.origin, directionVectorY3)
|
||||
_this.rayZ = new Cesium.Ray(_this.origin, directionVectorZ3)
|
||||
break;
|
||||
default:
|
||||
}
|
||||
_this.updateModel(_this._params.tx, _this._params.ty, _this._params.tz, _this._params.rx, _this._params.ry, _this._params.rz)
|
||||
_this.againArrow()
|
||||
}
|
||||
}
|
||||
|
||||
this.MapEvent.mouse_left_down((event, cartesian) => {
|
||||
let canvasCoordinates = viewer.scene.cartesianToCanvasCoordinates(this.origin)
|
||||
coordinatesDiffer.x = event.position.x - Math.floor(canvasCoordinates.x)
|
||||
coordinatesDiffer.y = event.position.y - Math.floor(canvasCoordinates.y)
|
||||
let pickedObjectArray = viewer.scene.drillPick(event.position, 10);
|
||||
for (let i = pickedObjectArray.length - 1; i >= 0; i--) {
|
||||
let pickedObject = pickedObjectArray[i]
|
||||
if (pickedObject && pickedObject.primitive && pickedObject.primitive._name) {
|
||||
if (_this.activeAxis) {
|
||||
_this.activeAxis = null
|
||||
_this.activeModelParam = null
|
||||
_this.controllerCallBack
|
||||
}
|
||||
else {
|
||||
switch (pickedObject.primitive._name) {
|
||||
case 'model_edit_xAxis':
|
||||
case 'model_edit_yAxis':
|
||||
case 'model_edit_zAxis':
|
||||
viewer.scene.screenSpaceCameraController.enableRotate = false;
|
||||
_this.activeAxis = pickedObject.primitive
|
||||
_this.activeModelParam = _this.initParam()
|
||||
pickedObject.primitive.appearance = new Cesium.PolylineMaterialAppearance({
|
||||
material: Cesium.Material.fromType(Cesium.Material.PolylineArrowType, {
|
||||
color: Cesium.Color.YELLOW,
|
||||
}),
|
||||
translucent: true,
|
||||
renderState: {
|
||||
depthTest: {
|
||||
enabled: false,
|
||||
},
|
||||
depthMask: false,
|
||||
depthFunction: Cesium.DepthFunction.ALWAYS,
|
||||
},
|
||||
})
|
||||
return;
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
this.MapEvent.mouse_left_up((event) => {
|
||||
viewer.scene.screenSpaceCameraController.enableRotate = true;
|
||||
for (let i = 0; i < _this.coordArrows.length; i++) {
|
||||
switch (_this.coordArrows[i]._name) {
|
||||
case 'model_edit_xAxis':
|
||||
_this.coordArrows[i].appearance = new Cesium.PolylineMaterialAppearance({
|
||||
material: Cesium.Material.fromType(Cesium.Material.PolylineArrowType, {
|
||||
color: Cesium.Color.RED,
|
||||
}),
|
||||
translucent: true,
|
||||
renderState: {
|
||||
depthTest: {
|
||||
enabled: false,
|
||||
},
|
||||
depthMask: false,
|
||||
depthFunction: Cesium.DepthFunction.ALWAYS,
|
||||
},
|
||||
})
|
||||
break;
|
||||
case 'model_edit_yAxis':
|
||||
_this.coordArrows[i].appearance = new Cesium.PolylineMaterialAppearance({
|
||||
material: Cesium.Material.fromType(Cesium.Material.PolylineArrowType, {
|
||||
color: Cesium.Color.LIME,
|
||||
}),
|
||||
translucent: true,
|
||||
renderState: {
|
||||
depthTest: {
|
||||
enabled: false,
|
||||
},
|
||||
depthMask: false,
|
||||
depthFunction: Cesium.DepthFunction.ALWAYS,
|
||||
},
|
||||
})
|
||||
break;
|
||||
case 'model_edit_zAxis':
|
||||
_this.coordArrows[i].appearance = new Cesium.PolylineMaterialAppearance({
|
||||
material: Cesium.Material.fromType(Cesium.Material.PolylineArrowType, {
|
||||
color: Cesium.Color.BLUE,
|
||||
}),
|
||||
translucent: true,
|
||||
renderState: {
|
||||
depthTest: {
|
||||
enabled: false,
|
||||
},
|
||||
depthMask: false,
|
||||
depthFunction: Cesium.DepthFunction.ALWAYS,
|
||||
},
|
||||
})
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
if (_this.activeAxis) {
|
||||
_this.activeAxis = null
|
||||
_this.activeModelParam = null
|
||||
_this.controllerCallBack
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 重新计算箭头位置
|
||||
againArrow() {
|
||||
let _that = (this._that || this)
|
||||
if (!_that.origin) {
|
||||
return
|
||||
}
|
||||
_that.initParam()
|
||||
_that.origin = new Cesium.Cartesian3.fromDegrees(_that._params.tx, _that._params.ty, _that._params.tz)
|
||||
let viewer = _that.viwer
|
||||
// 获取相机的位置
|
||||
var cameraPosition = viewer.camera.position;
|
||||
// 计算相机与目标坐标之间的距离
|
||||
var distance = Cesium.Cartesian3.distance(cameraPosition, _that.origin);
|
||||
let scale = distance / 15
|
||||
const matrix = Cesium.Transforms.eastNorthUpToFixedFrame(_that.origin)
|
||||
|
||||
let primitives = _that.coordArrows
|
||||
for (let i = 0; i < primitives.length; i++) {
|
||||
switch (primitives[i]._name) {
|
||||
case 'model_edit_xAxis':
|
||||
case 'model_edit_yAxis':
|
||||
case 'model_edit_zAxis':
|
||||
Cesium.Matrix4.multiplyByScale(matrix, new Cesium.Cartesian3(scale, scale, scale), primitives[i].modelMatrix)
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//重新计算圆
|
||||
againCircle() {
|
||||
let _that = (this._that || this)
|
||||
if (!_that.origin) {
|
||||
return
|
||||
}
|
||||
_that.initParam()
|
||||
_that.origin = new Cesium.Cartesian3.fromDegrees(_that._params.tx, _that._params.ty, _that._params.tz)
|
||||
let viewer = _that.viwer
|
||||
// 获取相机的位置
|
||||
var cameraPosition = viewer.camera.position;
|
||||
// 计算相机与目标坐标之间的距离
|
||||
var distance = Cesium.Cartesian3.distance(cameraPosition, _that.origin);
|
||||
let radius = distance / 15
|
||||
const matrix = Cesium.Transforms.eastNorthUpToFixedFrame(_that.origin)
|
||||
let primitives = _that.coordCircles
|
||||
for (let i = 0; i < primitives.length; i++) {
|
||||
// _that.viwer.scene.primitives.lowerToBottom(primitives[i])
|
||||
switch (primitives[i]._name) {
|
||||
case 'model_edit_zCircle':
|
||||
case 'model_edit_yCircle':
|
||||
case 'model_edit_xCircle':
|
||||
let scale = radius / 20
|
||||
Cesium.Matrix4.multiplyByScale(matrix, new Cesium.Cartesian3(scale, scale, scale), primitives[i].modelMatrix)
|
||||
primitives[i]._radius = radius
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始旋转编辑
|
||||
*/
|
||||
async editRtation() {
|
||||
this.destroy()
|
||||
this.activeState = 'rtation'
|
||||
this.MapEvent = new MouseEvent(this.sdk)
|
||||
const param = this.initParam()
|
||||
this.origin = Cesium.Cartesian3.fromDegrees(param.lng, param.lat, param.alt)
|
||||
this.createCircle(
|
||||
param.lng,
|
||||
param.lat,
|
||||
param.alt,
|
||||
20
|
||||
)
|
||||
// 监听相机移动
|
||||
this.viwer.camera.percentageChanged = 0.001
|
||||
this.viwer.camera.changed.addEventListener(this.againCircle, { _that: this });
|
||||
}
|
||||
|
||||
async createCircle(lng, lat, height, radius) {
|
||||
let _that = (this._that || this)
|
||||
let _this = this
|
||||
let viewer = this.viwer
|
||||
const position = []
|
||||
for (let i = 0; i <= 360; i += 3) {
|
||||
const sin = Math.sin(Cesium.Math.toRadians(i))
|
||||
const cos = Math.cos(Cesium.Math.toRadians(i))
|
||||
const x = radius * cos
|
||||
const y = radius * sin
|
||||
position.push(new Cesium.Cartesian3(x, y, 0))
|
||||
}
|
||||
const matrix = Cesium.Transforms.eastNorthUpToFixedFrame(
|
||||
new Cesium.Cartesian3.fromDegrees(lng, lat, height)
|
||||
)
|
||||
// 获取相机的位置
|
||||
var cameraPosition = viewer.camera.position;
|
||||
// 计算相机与目标坐标之间的距离
|
||||
var distance = Cesium.Cartesian3.distance(cameraPosition, this.origin);
|
||||
let newRadius = distance / 15
|
||||
let scale = newRadius / radius
|
||||
Cesium.Matrix4.multiplyByScale(matrix, new Cesium.Cartesian3(scale, scale, scale), matrix)
|
||||
// Cesium.Matrix4.multiply(
|
||||
// matrix,
|
||||
// x,
|
||||
// matrix
|
||||
// )
|
||||
//绕Z轴
|
||||
const axisSphereZ = await this.createAxisSphere(
|
||||
'model_edit_zCircle',
|
||||
position,
|
||||
matrix,
|
||||
Cesium.Color.RED,
|
||||
newRadius
|
||||
)
|
||||
viewer.scene.primitives.add(axisSphereZ)
|
||||
|
||||
//绕Y周
|
||||
const axisSphereY = await this.createAxisSphere(
|
||||
'model_edit_yCircle',
|
||||
position,
|
||||
matrix,
|
||||
Cesium.Color.BLUE,
|
||||
newRadius
|
||||
)
|
||||
viewer.scene.primitives.add(axisSphereY)
|
||||
let my = Cesium.Matrix3.fromRotationY(Cesium.Math.toRadians(90))
|
||||
let rotationY = Cesium.Matrix4.fromRotationTranslation(my)
|
||||
Cesium.Matrix4.multiply(
|
||||
axisSphereY.geometryInstances.modelMatrix,
|
||||
rotationY,
|
||||
axisSphereY.geometryInstances.modelMatrix
|
||||
)
|
||||
|
||||
//绕X周
|
||||
const axisSphereX = await this.createAxisSphere(
|
||||
'model_edit_xCircle',
|
||||
position,
|
||||
matrix,
|
||||
Cesium.Color.LIME,
|
||||
newRadius
|
||||
)
|
||||
viewer.scene.primitives.add(axisSphereX)
|
||||
let mx = Cesium.Matrix3.fromRotationX(Cesium.Math.toRadians(90))
|
||||
let rotationX = Cesium.Matrix4.fromRotationTranslation(mx)
|
||||
Cesium.Matrix4.multiply(
|
||||
axisSphereX.geometryInstances.modelMatrix,
|
||||
rotationX,
|
||||
axisSphereX.geometryInstances.modelMatrix
|
||||
)
|
||||
|
||||
let lastPickTime = 0;
|
||||
let timeoutEvent
|
||||
this.MapEvent.mouse_move((movement) => {
|
||||
moveEvent(movement)
|
||||
})
|
||||
|
||||
function moveEvent(movement) {
|
||||
if (!_this.activeCircle) {
|
||||
const now = Date.now();
|
||||
if (now - lastPickTime < 100) {
|
||||
clearTimeout(timeoutEvent)
|
||||
timeoutEvent = setTimeout(() => {
|
||||
moveEvent(movement)
|
||||
}, 100);
|
||||
return
|
||||
}
|
||||
clearTimeout(timeoutEvent)
|
||||
lastPickTime = now;
|
||||
let primitives = _that.coordCircles
|
||||
for (let i = 0; i < primitives.length; i++) {
|
||||
if (primitives[i].getGeometryInstanceAttributes) {
|
||||
let attributes = primitives[i].getGeometryInstanceAttributes(primitives[i]._name);
|
||||
switch (primitives[i]._name) {
|
||||
case 'model_edit_zCircle':
|
||||
attributes.color = Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED).value
|
||||
break;
|
||||
case 'model_edit_yCircle':
|
||||
attributes.color = Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.BLUE).value
|
||||
break;
|
||||
case 'model_edit_xCircle':
|
||||
attributes.color = Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.LIME).value
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
let pickedObjectArray = viewer.scene.drillPick(movement.endPosition, 10);
|
||||
for (let i = 0; i < pickedObjectArray.length; i++) {
|
||||
let pick = pickedObjectArray[i]
|
||||
if (pick && pick.primitive && pick.id) {
|
||||
let attributes = pick.primitive.getGeometryInstanceAttributes(pick.id);
|
||||
switch (pick.primitive._name) {
|
||||
case 'model_edit_zCircle':
|
||||
attributes.color = Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.YELLOW).value
|
||||
return;
|
||||
case 'model_edit_yCircle':
|
||||
attributes.color = Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.YELLOW).value
|
||||
return;
|
||||
case 'model_edit_xCircle':
|
||||
attributes.color = Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.YELLOW).value
|
||||
return;
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
let position1 = Cesium.SceneTransforms.wgs84ToWindowCoordinates(viewer.scene, _that.ciclkPosition);
|
||||
|
||||
let _rx = 0,
|
||||
_ry = 0,
|
||||
_rz = 0 //xyz方向的旋转量(度)
|
||||
if (!position1) {
|
||||
return
|
||||
}
|
||||
const _yPix = movement.startPosition.y - movement.endPosition.y
|
||||
const _xPix = movement.startPosition.x - movement.endPosition.x
|
||||
switch (_this.activeCircle._name) {
|
||||
case 'model_edit_xCircle':
|
||||
_ry = 1 * _xPix
|
||||
break;
|
||||
case 'model_edit_yCircle':
|
||||
_rx = 1 * _yPix
|
||||
break;
|
||||
case 'model_edit_zCircle':
|
||||
_rz = 1 * _xPix
|
||||
break;
|
||||
default:
|
||||
}
|
||||
_this._params.rx -= _rx
|
||||
if (_this._params.rx > 360) {
|
||||
_this._params.rx = 1
|
||||
}
|
||||
if (_this._params.rx < 0) {
|
||||
_this._params.rx = 360
|
||||
}
|
||||
let mx = Cesium.Matrix3.fromRotationX(
|
||||
Cesium.Math.toRadians(_this._params.rx)
|
||||
)
|
||||
_this._params.ry -= _ry
|
||||
if (_this._params.ry > 360) {
|
||||
_this._params.ry = 1
|
||||
}
|
||||
if (_this._params.ry < 0) {
|
||||
_this._params.ry = 360
|
||||
}
|
||||
_this._params.rz -= _rz
|
||||
if (_this._params.rz > 360) {
|
||||
_this._params.rz = 1
|
||||
}
|
||||
if (_this._params.rz < 0) {
|
||||
_this._params.rz = 360
|
||||
}
|
||||
_this.updateModel(_this._params.tx, _this._params.ty, _this._params.tz, _this._params.rx, _this._params.ry, _this._params.rz)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
this.MapEvent.mouse_left_down((event) => {
|
||||
let cartesian = viewer.scene.pickPosition(event.position);
|
||||
_that.ciclkPosition = cartesian
|
||||
let pickedObjectArray = viewer.scene.drillPick(event.position, 10);
|
||||
for (let i = 0; i < pickedObjectArray.length; i++) {
|
||||
let pickedObject = pickedObjectArray[i]
|
||||
if (pickedObject && pickedObject.primitive && pickedObject.id) {
|
||||
switch (pickedObject.primitive._name) {
|
||||
case 'model_edit_xCircle':
|
||||
case 'model_edit_yCircle':
|
||||
case 'model_edit_zCircle':
|
||||
viewer.scene.screenSpaceCameraController.enableRotate = false;
|
||||
let attributes = pickedObject.primitive.getGeometryInstanceAttributes(pickedObject.primitive._name);
|
||||
attributes.color = Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.YELLOW).value
|
||||
_this.activeCircle = pickedObject.primitive
|
||||
_this.activeModelParam = _this.initParam()
|
||||
return;
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
_this.activeCircle = null
|
||||
_this.activeModelParam = null
|
||||
viewer.scene.screenSpaceCameraController.enableRotate = true
|
||||
})
|
||||
this.MapEvent.mouse_left_up((event) => {
|
||||
viewer.scene.screenSpaceCameraController.enableRotate = true;
|
||||
let primitives = _this.coordCircles
|
||||
_this.activeCircle = null
|
||||
_this.activeModelParam = null
|
||||
for (let i = 0; i < primitives.length; i++) {
|
||||
if (primitives[i].getGeometryInstanceAttributes) {
|
||||
let attributes = primitives[i].getGeometryInstanceAttributes(primitives[i]._name);
|
||||
switch (primitives[i]._name) {
|
||||
case 'model_edit_zCircle':
|
||||
attributes.color = Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED).value
|
||||
break;
|
||||
case 'model_edit_yCircle':
|
||||
attributes.color = Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.BLUE).value
|
||||
break;
|
||||
case 'model_edit_xCircle':
|
||||
attributes.color = Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.LIME).value
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//更新模型位置
|
||||
updateModel(_tx, _ty, _tz, _rx = 0, _ry = 0, _rz = 0) {
|
||||
this._params.tx = _tx = parseFloat(parseFloat(_tx).toFixed(8))
|
||||
this._params.ty = _ty = parseFloat(parseFloat(_ty).toFixed(8))
|
||||
this._params.tz = _tz = parseFloat(parseFloat(_tz).toFixed(2))
|
||||
this._params.rx = _rx = parseFloat(_rx)
|
||||
this._params.ry = _ry = parseFloat(_ry)
|
||||
this._params.rz = _rz = parseFloat(_rz)
|
||||
this.options.position.lng = _tx
|
||||
this.options.position.lat = _ty
|
||||
this.options.position.alt = _tz
|
||||
this.options.rotate = { x: _rx, y: _ry, z: _rz }
|
||||
// this.model.position = new Cesium.Cartesian3.fromDegrees(_tx, _ty, _tz)
|
||||
// this.model.rotate = { x: _rx, y: _ry, z: _rz }
|
||||
// let mx = Cesium.Matrix3.fromRotationX(
|
||||
// Cesium.Math.toRadians(_rx)
|
||||
// )
|
||||
// let my = Cesium.Matrix3.fromRotationY(
|
||||
// Cesium.Math.toRadians(_ry)
|
||||
// )
|
||||
// let mz = Cesium.Matrix3.fromRotationZ(
|
||||
// Cesium.Math.toRadians(_rz)
|
||||
// )
|
||||
// // 平移
|
||||
// let m = Cesium.Transforms.eastNorthUpToFixedFrame(new Cesium.Cartesian3.fromDegrees(_tx, _ty, _tz))
|
||||
// // 旋转
|
||||
// let rotationX = Cesium.Matrix4.fromRotationTranslation(mx)
|
||||
// let rotationY = Cesium.Matrix4.fromRotationTranslation(my)
|
||||
// let rotationZ = Cesium.Matrix4.fromRotationTranslation(mz)
|
||||
// let originalMatrix = new Cesium.Matrix4()
|
||||
// Cesium.Matrix4.multiply(m, rotationX, originalMatrix)
|
||||
// Cesium.Matrix4.multiply(originalMatrix, rotationY, originalMatrix)
|
||||
// Cesium.Matrix4.multiply(originalMatrix, rotationZ, this.model.modelMatrix)
|
||||
this.controllerCallBack
|
||||
}
|
||||
|
||||
set controllerCallBack(callback) {
|
||||
this._controllerCallBack = callback
|
||||
}
|
||||
get controllerCallBack() {
|
||||
this._controllerCallBack && this._controllerCallBack(this.options, this.activeAxis ? false : true)
|
||||
}
|
||||
|
||||
createAxisArrow(name, position, matrix, color) {
|
||||
let result = new Cesium.Primitive({
|
||||
geometryInstances: new Cesium.GeometryInstance({
|
||||
id: name,
|
||||
geometry: new Cesium.PolylineGeometry({
|
||||
positions: position,
|
||||
width: 20
|
||||
}),
|
||||
attributes: {
|
||||
color: Cesium.ColorGeometryInstanceAttribute.fromColor(color)
|
||||
}
|
||||
}),
|
||||
releaseGeometryInstances: false,
|
||||
appearance: new Cesium.PolylineMaterialAppearance({
|
||||
material: Cesium.Material.fromType(Cesium.Material.PolylineArrowType, {
|
||||
color: color,
|
||||
}),
|
||||
translucent: true,
|
||||
renderState: {
|
||||
depthTest: {
|
||||
enabled: false,
|
||||
},
|
||||
depthMask: false,
|
||||
depthFunction: Cesium.DepthFunction.ALWAYS,
|
||||
},
|
||||
}),
|
||||
modelMatrix: matrix
|
||||
})
|
||||
result._name = name
|
||||
this.coordArrows.push(result)
|
||||
return result
|
||||
}
|
||||
createAxisCircular(name, position, matrix, color) {
|
||||
let result = new Cesium.Primitive({
|
||||
geometryInstances: new Cesium.GeometryInstance({
|
||||
geometry: new Cesium.EllipseGeometry(
|
||||
{
|
||||
center: { x: 1, y: 1, z: 1 },
|
||||
semiMinorAxis: 500000.0,
|
||||
semiMajorAxis: 1000000.0,
|
||||
rotation: Cesium.Math.PI_OVER_FOUR,
|
||||
vertexFormat: Cesium.VertexFormat.POSITION_AND_ST
|
||||
}
|
||||
)
|
||||
}),
|
||||
releaseGeometryInstances: false,
|
||||
appearance: new Cesium.EllipsoidSurfaceAppearance({
|
||||
material: new Cesium.Material({
|
||||
fabric: {
|
||||
type: 'Color',
|
||||
uniforms: {
|
||||
color: Cesium.Color.YELLOW
|
||||
}
|
||||
}
|
||||
})
|
||||
}),
|
||||
modelMatrix: matrix
|
||||
})
|
||||
result._name = name
|
||||
this.coordArrows.push(result)
|
||||
return result
|
||||
}
|
||||
|
||||
createAxisSphere(name, position, matrix, color, radius) {
|
||||
let result = new Cesium.Primitive({
|
||||
geometryInstances: new Cesium.GeometryInstance({
|
||||
id: name,
|
||||
geometry: new Cesium.PolylineGeometry({
|
||||
positions: position,
|
||||
width: 5
|
||||
}),
|
||||
attributes: {
|
||||
color: Cesium.ColorGeometryInstanceAttribute.fromColor(color)
|
||||
}
|
||||
}),
|
||||
releaseGeometryInstances: false,
|
||||
appearance: new Cesium.PolylineColorAppearance({
|
||||
translucent: true,
|
||||
renderState: {
|
||||
depthTest: {
|
||||
enabled: false,
|
||||
},
|
||||
depthMask: false,
|
||||
depthFunction: Cesium.DepthFunction.ALWAYS,
|
||||
},
|
||||
}),
|
||||
modelMatrix: matrix
|
||||
})
|
||||
result._radius = radius
|
||||
result._name = name
|
||||
this.coordCircles.push(result)
|
||||
return result
|
||||
}
|
||||
|
||||
removeCoordArrows() {
|
||||
for (let i = 0; i < this.coordArrows.length; i++) {
|
||||
this.viwer.scene.primitives.remove(this.coordArrows[i])
|
||||
}
|
||||
this.coordArrows = []
|
||||
}
|
||||
|
||||
removeCoordCircle() {
|
||||
for (let i = 0; i < this.coordCircles.length; i++) {
|
||||
this.viwer.scene.primitives.remove(this.coordCircles[i])
|
||||
}
|
||||
this.coordCircles = []
|
||||
}
|
||||
|
||||
removeAllTools() {
|
||||
this.removeCoordArrows()
|
||||
this.removeCoordCircle()
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭/注销
|
||||
*/
|
||||
destroy() {
|
||||
this.removeAllTools()
|
||||
this.activeAxis = undefined
|
||||
this.activeState = undefined
|
||||
this.MapEvent && this.MapEvent.destroy()
|
||||
this.viwer.camera.changed.removeEventListener(this.againArrow)
|
||||
this.viwer.camera.changed.removeEventListener(this.againCircle)
|
||||
}
|
||||
|
||||
getActiveState() {
|
||||
return this.activeState
|
||||
}
|
||||
|
||||
update() {
|
||||
this.againArrow()
|
||||
this.againCircle()
|
||||
}
|
||||
}
|
||||
export default ControllerObject
|
||||
88
src/DZ/XJ/BatchLoadObjModel/index.js
Normal file
88
src/DZ/XJ/BatchLoadObjModel/index.js
Normal file
@ -0,0 +1,88 @@
|
||||
import { getHost, getToken } from "../../../on";
|
||||
import BaseLoadObjModel from '../../../Obj/Base/LoadObjModel'
|
||||
import LoadObjModel from '../LoadObjModel'
|
||||
export default class BatchLoadObjModel {
|
||||
constructor(sdk, options = {}) {
|
||||
this.sdk = sdk
|
||||
this.options = { ...options }
|
||||
this.options.show = (options.show || options.show === false) ? options.show : true
|
||||
this.options.host = this.options.host || getHost()
|
||||
this.objModelObject = []
|
||||
this._loaded = false
|
||||
this._loadEvent = void 0
|
||||
this.on()
|
||||
}
|
||||
|
||||
get show() {
|
||||
return this.options.show
|
||||
}
|
||||
|
||||
set show(v) {
|
||||
if (typeof v === "boolean") {
|
||||
this.options.show = v
|
||||
for (let i = 0; i < this.objModelObject.length; i++) {
|
||||
this.objModelObject[i].load(() => {
|
||||
this.objModelObject[i].show = v
|
||||
})
|
||||
}
|
||||
} else {
|
||||
console.error("参数必须为boolean")
|
||||
}
|
||||
}
|
||||
|
||||
async on() {
|
||||
let url = ""
|
||||
if (this.options.host.endsWith("yjearth4.0"))
|
||||
url = this.options.host + '/api/v1/source/obj'
|
||||
else
|
||||
url = this.options.host + '/yjearth4.0/api/v1/source/obj'
|
||||
if (this.options.code) {
|
||||
url = url + '?code=' + this.options.code
|
||||
}
|
||||
const res = await fetch(url, {
|
||||
method: 'get',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
"token": getToken(),
|
||||
"Authorization": "Bearer " + getToken(),
|
||||
}
|
||||
});
|
||||
if (res.ok) {
|
||||
this.objModelObject = []
|
||||
this.list = (await res.json()).data;
|
||||
if (this.options.count) {
|
||||
this.list = this.list.splice(0, this.options.count)
|
||||
}
|
||||
for (let i = 0; i < this.list.length; i++) {
|
||||
let options = JSON.parse(this.list[i].detail)
|
||||
options.host = this.options.host
|
||||
if (this.options.show || this.options.show === false) {
|
||||
options.show = this.options.show
|
||||
}
|
||||
let object = new LoadObjModel(this.sdk, options);
|
||||
this.objModelObject.push(object)
|
||||
}
|
||||
this._loaded = true
|
||||
if (this._loadEvent) {
|
||||
this._loadEvent()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
remove() {
|
||||
for (let i = 0; i < this.objModelObject.length; i++) {
|
||||
this.objModelObject[i].load(() => {
|
||||
this.objModelObject[i].remove()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
load(callback) {
|
||||
if (this._loaded) {
|
||||
callback();
|
||||
}
|
||||
else {
|
||||
this._loadEvent = callback
|
||||
}
|
||||
}
|
||||
}
|
||||
180
src/DZ/XJ/LoadObjModel/index.js
Normal file
180
src/DZ/XJ/LoadObjModel/index.js
Normal file
@ -0,0 +1,180 @@
|
||||
import AModelLoader from '../../../Obj/Base/LoadObjModel/AModelLoader'
|
||||
import { getHost, getToken } from "../../../on";
|
||||
import BaseLoadObjModel from '../../../Obj/Base/LoadObjModel'
|
||||
export default class LoadObjModel extends BaseLoadObjModel {
|
||||
constructor(sdk, options, CallBack) {
|
||||
super(sdk, options, CallBack)
|
||||
this._loadEvent = void 0
|
||||
this._loaded = false
|
||||
this.options.objId = options.objId
|
||||
this.options.videoId = options.videoId
|
||||
this.options.videoType = options.videoType || 'flv'
|
||||
}
|
||||
|
||||
async addResource() {
|
||||
let that = this
|
||||
that.options.xmlURL = that.options.objUrl.replace('.obj', '.xml')
|
||||
if (that.options.xmlURL !== '') {
|
||||
const xml = await fetch(that.options.xmlURL)
|
||||
if (xml.ok) {
|
||||
const xmlString = await xml.text()
|
||||
const parser = new DOMParser()
|
||||
const xmlDoc = parser.parseFromString(xmlString, 'text/xml')
|
||||
// console.log('xmlDocxmlDocxmlDoc', xmlDoc)
|
||||
const position = xmlDoc
|
||||
.getElementsByTagName('Position')[0]
|
||||
.textContent.split(',')
|
||||
// const bbox = xmlDoc.getElementsByTagName('bbox')[0]
|
||||
const crs = xmlDoc.getElementsByTagName('Crs')[0].textContent
|
||||
const result = that.convert(
|
||||
[{ x: position[0], y: position[1], z: position[2] }],
|
||||
crs,
|
||||
'EPSG:4326'
|
||||
)
|
||||
|
||||
that.options.position = that.options.position || { lng: result.points[0].x, lat: result.points[0].y, alt: result.points[0].z }
|
||||
that.ControllerObject.position = that.options.position
|
||||
const scene = that.viwer.scene
|
||||
const origin = Cesium.Cartesian3.fromDegrees(
|
||||
that.options.position.lng,
|
||||
that.options.position.lat,
|
||||
that.options.position.alt
|
||||
)
|
||||
const obj_modelMatrix = Cesium.Transforms.headingPitchRollToFixedFrame(
|
||||
origin,
|
||||
new Cesium.HeadingPitchRoll(
|
||||
Cesium.Math.toRadians(0.85),
|
||||
Cesium.Math.toRadians(0),
|
||||
Cesium.Math.toRadians(0)
|
||||
)
|
||||
)
|
||||
let objLoader = new AModelLoader(that.viwer.scene.context)
|
||||
let obj = await objLoader.Load(that.options.objUrl, that.options.videoId, that.options.host)
|
||||
obj.modelMatrix = obj_modelMatrix
|
||||
obj.show = that.options.show
|
||||
obj.setFlvVideo(that.options.videoUrl)
|
||||
scene.primitives.add(obj)
|
||||
that.primitive = obj
|
||||
that.controllerCallBack({
|
||||
rotate: { x: that.options.roll, y: -that.options.pitch, z: -that.options.heading },
|
||||
position: { ...that.options.position }
|
||||
})
|
||||
that.loaded = true
|
||||
that._loaded = true
|
||||
if (that._loadEvent) {
|
||||
that._loadEvent()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return
|
||||
}
|
||||
if (that.options.objUrl === '') {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
async requestResource() {
|
||||
let that = this
|
||||
if(!that._loaded) {
|
||||
if(that.options.objId) {
|
||||
that.options.objUrl = await that.requestObjResource()
|
||||
}
|
||||
if(that.options.videoId) {
|
||||
that.options.videoUrl = await that.requestVideoResource()
|
||||
}
|
||||
await that.addResource()
|
||||
}
|
||||
}
|
||||
|
||||
requestObjResource() {
|
||||
let host = ""
|
||||
if (this.options.host.endsWith("yjearth4.0"))
|
||||
host = this.options.host
|
||||
else
|
||||
host = this.options.host + '/yjearth4.0'
|
||||
let url = host + '/obj/' + this.options.objId
|
||||
return fetch(url, {
|
||||
method: 'get',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
"token": getToken(),
|
||||
"Authorization": "Bearer " + getToken(),
|
||||
}
|
||||
}).then(async (res) => {
|
||||
let text = await res.text()
|
||||
text = JSON.parse(text)
|
||||
if ([0, 200].includes(text.code)) {
|
||||
if (text.data.objPath.length)
|
||||
return host + '/obj/wirte/file/' + text.data.objPath
|
||||
else
|
||||
console.warn('资源不存在')
|
||||
return
|
||||
} else {
|
||||
console.warn(text.msg || text.message)
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
requestVideoResource() {
|
||||
let host = ""
|
||||
if (this.options.host.endsWith("yjearth4.0"))
|
||||
host = this.options.host
|
||||
else
|
||||
host = this.options.host + '/yjearth4.0'
|
||||
let url = host + '/videoFusion/' + this.options.videoId
|
||||
return fetch(url, {
|
||||
method: 'get',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
"token": getToken(),
|
||||
"Authorization": "Bearer " + getToken(),
|
||||
}
|
||||
}).then(async (res) => {
|
||||
let text = await res.text()
|
||||
text = JSON.parse(text)
|
||||
if ([0, 200].includes(text.code)) {
|
||||
if (text.data.deviceCode.length) {
|
||||
return fetch(host+'/videoFusion/vide/stream', {
|
||||
method: 'post',
|
||||
body: JSON.stringify({type: 'flv', deviceCode: text.data.deviceCode}),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
"token": getToken(),
|
||||
"Authorization": "Bearer " + getToken(),
|
||||
}
|
||||
}).then(async (res2) => {
|
||||
let text2 = await res2.text()
|
||||
text2 = JSON.parse(text2)
|
||||
if ([0, 200].includes(text2.code)) {
|
||||
if (text2.data.flv && text2.data.flv.length) {
|
||||
return text2.data.flv
|
||||
}
|
||||
else
|
||||
console.warn('地址不存在')
|
||||
return
|
||||
} else {
|
||||
console.warn(text2.msg || text2.message)
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
else
|
||||
console.warn('设备不存在')
|
||||
return
|
||||
} else {
|
||||
console.warn(text.msg || text.message)
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
load(callback) {
|
||||
if (this._loaded) {
|
||||
callback();
|
||||
}
|
||||
else {
|
||||
this._loadEvent = callback
|
||||
}
|
||||
}
|
||||
}
|
||||
69
src/Draw/draw.js
Normal file
69
src/Draw/draw.js
Normal file
@ -0,0 +1,69 @@
|
||||
/**
|
||||
* @name: draw
|
||||
* @author: Administrator
|
||||
* @date: 2022-06-14 16:29
|
||||
* @description:draw
|
||||
* @update: 2022-06-14 16:29
|
||||
*/
|
||||
import Tools from '../Tools'
|
||||
import { get2DView } from '../Global/MultiViewportMode'
|
||||
|
||||
class Draw extends Tools {
|
||||
/**
|
||||
* @constructor
|
||||
* */
|
||||
constructor(sdk, options = {}, is2D = false) {
|
||||
super(sdk, options)
|
||||
this.viewer = sdk.viewer
|
||||
this.entityHasCreated = false
|
||||
this.event = null
|
||||
this.tip = null
|
||||
this.points_ids = []
|
||||
this.color = options.color || 'rgba(185,14,14,0.58)'
|
||||
this._is2D = is2D
|
||||
this._sdk2D = get2DView()
|
||||
}
|
||||
|
||||
create_point(cartesian, viewer = this.viewer) {
|
||||
let id = this.randomString()
|
||||
viewer.entities.add(
|
||||
new Cesium.Entity({
|
||||
id: id,
|
||||
position: cartesian,
|
||||
billboard: {
|
||||
image: this.getSourceRootPath() + '/img/point.png',
|
||||
// verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
color: Cesium.Color.WHITE.withAlpha(0.99)
|
||||
// disableDepthTestDistance: 1000000
|
||||
},
|
||||
})
|
||||
)
|
||||
return id
|
||||
}
|
||||
|
||||
remove_entity(id) {
|
||||
this.viewer.entities.removeById(id)
|
||||
if (!this._is2D && this._sdk2D && this._sdk2D.viewer && this._sdk2D.viewer.entities) {
|
||||
this._sdk2D.viewer.entities.removeById(id)
|
||||
}
|
||||
}
|
||||
|
||||
start() {
|
||||
// this.setPickStatus(false)
|
||||
}
|
||||
|
||||
end() {
|
||||
// this.setPickStatus(true)
|
||||
|
||||
YJ.Measure.SetMeasureStatus(false)
|
||||
this.entityHasCreated = false
|
||||
this.event && this.event.destroy()
|
||||
this.event2D && this.event2D.destroy()
|
||||
this.tip && this.tip.destroy()
|
||||
this.points_ids.forEach((id) => {
|
||||
this.remove_entity(id)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default Draw
|
||||
595
src/Draw/drawAssemble.js
Normal file
595
src/Draw/drawAssemble.js
Normal file
@ -0,0 +1,595 @@
|
||||
import MouseTip from '../MouseTip'
|
||||
import MouseEvent from '../Event'
|
||||
import Draw from './draw'
|
||||
|
||||
const transformCartesianToWGS84 = cartesian => {
|
||||
let ellipsoid = Cesium.Ellipsoid.WGS84
|
||||
let cartographic = ellipsoid.cartesianToCartographic(cartesian)
|
||||
const x = Cesium.Math.toDegrees(cartographic.longitude)
|
||||
const y = Cesium.Math.toDegrees(cartographic.latitude)
|
||||
const z = cartographic.height
|
||||
return { x, y, z }
|
||||
}
|
||||
|
||||
/**
|
||||
* @extends Draw*/
|
||||
class DrawAssemble extends Draw {
|
||||
/**
|
||||
* @constructor
|
||||
* @param sdk
|
||||
* @param [options] {object} 面属性
|
||||
* @param [options.color=rgba(185,14,14,0.58)] {object} 线属性
|
||||
|
||||
* */
|
||||
constructor(sdk, options = {}) {
|
||||
super(sdk, options)
|
||||
this.points = null
|
||||
this.polygonHasCreated = false
|
||||
}
|
||||
|
||||
static polygon(that, viewer = that.viewer) {
|
||||
let id = that.randomString()
|
||||
return viewer.entities.add(
|
||||
new Cesium.Entity({
|
||||
name: 'AssemblePolygon',
|
||||
id,
|
||||
polygon: {
|
||||
hierarchy: new Cesium.CallbackProperty(e => {
|
||||
let arr = that.computeAssemble(that.positions)
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
if (isNaN(arr[i].x)) {
|
||||
arr = []
|
||||
break
|
||||
}
|
||||
}
|
||||
return new Cesium.PolygonHierarchy(arr)
|
||||
}, false),
|
||||
material: Cesium.Color.fromCssColorString(that.color),
|
||||
outline: true,
|
||||
outlineColor: Cesium.Color.GREEN,
|
||||
zIndex: 99999999
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @desc 开始动态绘制面
|
||||
* @method start
|
||||
* @param cb {function} 回调函数
|
||||
* @memberOf DrawPolygon
|
||||
* @example draw.start((err,positions)=>{
|
||||
*
|
||||
* })
|
||||
* */
|
||||
start(cb) {
|
||||
let that = this
|
||||
// eslint-disable-next-line no-undef
|
||||
if (YJ.Measure.GetMeasureStatus()) {
|
||||
cb('上一次测量未结束')
|
||||
} else {
|
||||
super.start()
|
||||
// eslint-disable-next-line no-undef
|
||||
YJ.Measure.SetMeasureStatus(true)
|
||||
let into
|
||||
this.tip = new MouseTip('左键确定,右键取消;', that.sdk)
|
||||
this.event = new MouseEvent(that.sdk)
|
||||
this.positions = []
|
||||
this.points_ids = [] //存放左键点击时临时添加的point的id
|
||||
let cache_positions = []
|
||||
let cache_84_position = []
|
||||
this.anchorpoints = []
|
||||
this.event.mouse_left((movement, cartesian) => {
|
||||
if (into === '2D') {
|
||||
return
|
||||
}
|
||||
into = '3D'
|
||||
if (!cartesian) return
|
||||
if (this.anchorpoints.length === 3) {
|
||||
this.anchorpoints[1] = cartesian;
|
||||
}
|
||||
else {
|
||||
this.anchorpoints.push(cartesian)
|
||||
}
|
||||
|
||||
cache_positions.push(this.cartesian3Towgs84(cartesian, this.viewer))
|
||||
// console.log(this.cartesian3Towgs84(cartesian))
|
||||
this.points_ids.push(this.create_point(cartesian))
|
||||
if (this.points_ids.length === 3) {
|
||||
let array = [cache_positions[0], cache_positions[2], cache_positions[1]]
|
||||
cb(null, array)
|
||||
this.end()
|
||||
}
|
||||
})
|
||||
this.event.mouse_move((movement, cartesian) => {
|
||||
if (into === '2D') {
|
||||
return
|
||||
}
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
movement.endPosition.x,
|
||||
movement.endPosition.y
|
||||
)
|
||||
if (!cartesian || this.points_ids.length === 0) return
|
||||
if (cache_positions.length > 1) {
|
||||
this.positions = [cache_positions[0], this.cartesian3Towgs84(cartesian, this.viewer), cache_positions[1]]
|
||||
}
|
||||
else {
|
||||
this.positions = [cache_positions[0], this.cartesian3Towgs84(cartesian, this.viewer)]
|
||||
}
|
||||
if (this.points_ids.length === 1 && !Cesium.defined(this.assemblePolygon)) {
|
||||
this.assemblePolygon = DrawAssemble.polygon(this)
|
||||
}
|
||||
if (this.anchorpoints.length >= 2) {
|
||||
if (this.points_ids.length === 1) {
|
||||
let pnts = new Array();
|
||||
this.positions.forEach((item) => {
|
||||
pnts.push([item.lng, item.lat]);
|
||||
});
|
||||
|
||||
let mid = P.PlotUtils.mid(pnts[0], pnts[1])
|
||||
let d = P.PlotUtils.distance(pnts[0], mid) / 0.9
|
||||
let pnt = P.PlotUtils.getThirdPoint(pnts[0], mid, P.Constants.HALF_PI, d, true)
|
||||
this.positions = [this.positions[0], { lng: pnt[0], lat: pnt[1] }, this.positions[1]];
|
||||
}
|
||||
//替换中间点
|
||||
this.anchorpoints[1] = cartesian;
|
||||
}
|
||||
else {
|
||||
this.anchorpoints.push(cartesian)
|
||||
}
|
||||
})
|
||||
this.event.mouse_right((movement, cartesian) => {
|
||||
if (into === '2D') {
|
||||
return
|
||||
}
|
||||
cb(null)
|
||||
this.end()
|
||||
})
|
||||
|
||||
this.event.gesture_pinck_start((movement, cartesian) => {
|
||||
if (into === '2D') {
|
||||
return
|
||||
}
|
||||
let startTime = new Date()
|
||||
this.event.gesture_pinck_end(() => {
|
||||
let endTime = new Date()
|
||||
if (endTime - startTime >= 500) {
|
||||
this.end()
|
||||
cb(false)
|
||||
}
|
||||
else {
|
||||
if (this.anchorpoints.length === 2) {
|
||||
this.anchorpoints.push(cartesian)
|
||||
cb(null, this.positions)
|
||||
this.end()
|
||||
}
|
||||
else {
|
||||
if (!cartesian || Cesium.defined(this.assemblePolygon)) return
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
(movement.position1.x + movement.position2.x) / 2,
|
||||
(movement.position1.y + movement.position2.y) / 2
|
||||
)
|
||||
this.anchorpoints.push(cartesian)
|
||||
this.assemblePolygon = DrawAssemble.polygon(this)
|
||||
cache_positions.push(this.cartesian3Towgs84(cartesian))
|
||||
// console.log(this.cartesian3Towgs84(cartesian))
|
||||
this.points_ids.push(this.create_point(cartesian))
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
if (!this._is2D && this._sdk2D) {
|
||||
this.event2D = new MouseEvent(this._sdk2D)
|
||||
this.event2D.mouse_left((movement, cartesian) => {
|
||||
if (into === '3D') {
|
||||
return
|
||||
}
|
||||
into = '2D'
|
||||
if (!cartesian) return
|
||||
if (this.anchorpoints.length === 3) {
|
||||
this.anchorpoints[1] = cartesian;
|
||||
}
|
||||
else {
|
||||
this.anchorpoints.push(cartesian)
|
||||
}
|
||||
|
||||
cache_positions.push(this.cartesian3Towgs84(cartesian, this.viewer))
|
||||
// console.log(this.cartesian3Towgs84(cartesian))
|
||||
this.points_ids.push(this.create_point(cartesian, this._sdk2D.viewer))
|
||||
if (this.points_ids.length === 3) {
|
||||
let array = [cache_positions[0], cache_positions[2], cache_positions[1]]
|
||||
cb(null, array)
|
||||
this.end()
|
||||
}
|
||||
})
|
||||
this.event2D.mouse_move((movement, cartesian) => {
|
||||
if (into === '3D') {
|
||||
return
|
||||
}
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
movement.endPosition.x + this.viewer.canvas.width,
|
||||
movement.endPosition.y
|
||||
)
|
||||
if (!cartesian || this.points_ids.length === 0) return
|
||||
if (cache_positions.length > 1) {
|
||||
this.positions = [cache_positions[0], this.cartesian3Towgs84(cartesian, this.viewer), cache_positions[1]]
|
||||
}
|
||||
else {
|
||||
this.positions = [cache_positions[0], this.cartesian3Towgs84(cartesian, this.viewer)]
|
||||
}
|
||||
if (this.points_ids.length === 1 && !Cesium.defined(this.assemblePolygon)) {
|
||||
this.assemblePolygon = DrawAssemble.polygon(this, this._sdk2D.viewer)
|
||||
}
|
||||
if (this.anchorpoints.length >= 2) {
|
||||
if (this.points_ids.length === 1) {
|
||||
let pnts = new Array();
|
||||
this.positions.forEach((item) => {
|
||||
pnts.push([item.lng, item.lat]);
|
||||
});
|
||||
|
||||
let mid = P.PlotUtils.mid(pnts[0], pnts[1])
|
||||
let d = P.PlotUtils.distance(pnts[0], mid) / 0.9
|
||||
let pnt = P.PlotUtils.getThirdPoint(pnts[0], mid, P.Constants.HALF_PI, d, true)
|
||||
this.positions = [this.positions[0], { lng: pnt[0], lat: pnt[1] }, this.positions[1]];
|
||||
}
|
||||
//替换中间点
|
||||
this.anchorpoints[1] = cartesian;
|
||||
}
|
||||
else {
|
||||
this.anchorpoints.push(cartesian)
|
||||
}
|
||||
})
|
||||
this.event2D.mouse_right((movement, cartesian) => {
|
||||
if (into === '3D') {
|
||||
return
|
||||
}
|
||||
cb(null)
|
||||
this.end()
|
||||
})
|
||||
|
||||
this.event2D.gesture_pinck_start((movement, cartesian) => {
|
||||
if (into === '3D') {
|
||||
return
|
||||
}
|
||||
let startTime = new Date()
|
||||
this.event2D.gesture_pinck_end(() => {
|
||||
let endTime = new Date()
|
||||
if (endTime - startTime >= 500) {
|
||||
this.end()
|
||||
cb(false)
|
||||
}
|
||||
else {
|
||||
if (this.anchorpoints.length === 2) {
|
||||
this.anchorpoints.push(cartesian)
|
||||
cb(null, this.positions)
|
||||
this.end()
|
||||
}
|
||||
else {
|
||||
if (!cartesian || Cesium.defined(this.assemblePolygon)) return
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
((movement.position1.x + movement.position2.x) / 2) + this.viewer.canvas.width,
|
||||
(movement.position1.y + movement.position2.y) / 2
|
||||
)
|
||||
this.anchorpoints.push(cartesian)
|
||||
this.assemblePolygon = DrawAssemble.polygon(this, this._sdk2D.viewer)
|
||||
cache_positions.push(this.cartesian3Towgs84(cartesian))
|
||||
// console.log(this.cartesian3Towgs84(cartesian))
|
||||
this.points_ids.push(this.create_point(cartesian, this._sdk2D.viewer))
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end() {
|
||||
super.end();
|
||||
this.viewer.entities.remove(this.assemblePolygon)
|
||||
if (!this._is2D && this._sdk2D) {
|
||||
this._sdk2D.viewer.entities.remove(this.assemblePolygon)
|
||||
}
|
||||
}
|
||||
|
||||
// computeAssemblePoints(anchorpoints) {
|
||||
// let points = []
|
||||
|
||||
// let originP = transformCartesianToWGS84(anchorpoints[0])
|
||||
// let lastP = anchorpoints[1]
|
||||
// ? transformCartesianToWGS84(anchorpoints[1])
|
||||
// : { x: originP.x + 0.00001, y: originP.y + 0.00001, z: originP.z }
|
||||
// let vectorOL = { x: lastP.x - originP.x, y: lastP.y - originP.y }
|
||||
// let dOL = Math.sqrt(vectorOL.x * vectorOL.x + vectorOL.y * vectorOL.y)
|
||||
// let v_O_P1_lr = this.calculateVector(
|
||||
// vectorOL,
|
||||
// Math.PI / 3,
|
||||
// (Math.sqrt(3) / 12) * dOL
|
||||
// )
|
||||
// let originP_P1 = v_O_P1_lr[1]
|
||||
// let p1 = { x: originP.x + originP_P1.x, y: originP.y + originP_P1.y }
|
||||
// let p2 = { x: (originP.x + lastP.x) / 2, y: (originP.y + lastP.y) / 2 }
|
||||
// let v_L_P3_lr = this.calculateVector(
|
||||
// vectorOL,
|
||||
// (Math.PI * 2) / 3,
|
||||
// (Math.sqrt(3) / 12) * dOL
|
||||
// )
|
||||
// let lastP_P3 = v_L_P3_lr[1]
|
||||
// let p3 = { x: lastP.x + lastP_P3.x, y: lastP.y + lastP_P3.y }
|
||||
// let v_O_P5_lr = this.calculateVector(vectorOL, Math.PI / 2, (1 / 2) * dOL)
|
||||
// let v_O_P5 = v_O_P5_lr[0]
|
||||
// let p5 = { x: v_O_P5.x + p2.x, y: v_O_P5.y + p2.y }
|
||||
// let p0 = originP
|
||||
// let p4 = lastP
|
||||
// points.push(p0, p1, p2, p3, p4, p5)
|
||||
// const closeCardinal = this.createCloseCardinal(points)
|
||||
// const fb_points = this.calculatePointsFBZ3(closeCardinal, 100)
|
||||
// let result = []
|
||||
// let result2 = []
|
||||
// for (let index = 0; index < fb_points.length; index++) {
|
||||
// const ele = fb_points[index]
|
||||
// let obj = {
|
||||
// lng: ele.x,
|
||||
// lat: ele.y,
|
||||
// alt: 0
|
||||
// }
|
||||
// result.push(ele.x, ele.y, 0)
|
||||
// result2.push(obj)
|
||||
// }
|
||||
// this.position = result2
|
||||
// this.points = result
|
||||
// }
|
||||
|
||||
// computeAssemblePoints2(anchorpoints) {
|
||||
// let points = anchorpoints.length;
|
||||
// if (points < 2) {
|
||||
// return false
|
||||
// } else {
|
||||
// let pnts = new Array();
|
||||
// anchorpoints.forEach((item) => {
|
||||
// let posLonLat = this.cartesian3Towgs84(item, this.viewer);;
|
||||
// pnts.push([posLonLat.lng, posLonLat.lat]);
|
||||
// });
|
||||
// //console.log("pnts6666",pnts);
|
||||
// // pnts.push(tailPoint);
|
||||
// // pnts.push(headerPoint);
|
||||
|
||||
// if (pnts.length === 2) {
|
||||
// let mid = P.PlotUtils.mid(pnts[0], pnts[1])
|
||||
// //let d = utils.MathDistance(pnts[0], mid) / 0.9
|
||||
// let d = P.PlotUtils.distance(pnts[0], mid) / 0.9
|
||||
// //console.log("d",d);
|
||||
// let pnt = P.PlotUtils.getThirdPoint(pnts[0], mid, P.Constants.HALF_PI, d, true)
|
||||
// pnts = [pnts[0], pnt, pnts[1]];
|
||||
// //console.log("pnt",pnt);
|
||||
// //createPoint(Cesium.Cartesian3.fromDegrees(pnt[0], pnt[1]));
|
||||
// }
|
||||
// let mid = P.PlotUtils.mid(pnts[0], pnts[2])
|
||||
// pnts.push(mid, pnts[0], pnts[1])
|
||||
|
||||
// let [normals, pnt1, pnt2, pnt3, result, result2] = [[], undefined, undefined, undefined, [], []]
|
||||
// for (let i = 0; i < pnts.length - 2; i++) {
|
||||
// pnt1 = pnts[i]
|
||||
// pnt2 = pnts[i + 1]
|
||||
// pnt3 = pnts[i + 2]
|
||||
// let normalPoints = P.PlotUtils.getBisectorNormals(0.4, pnt1, pnt2, pnt3)
|
||||
// normals = normals.concat(normalPoints)
|
||||
// }
|
||||
// let count = normals.length
|
||||
// normals = [normals[count - 1]].concat(normals.slice(0, count - 1))
|
||||
// for (let i = 0; i < pnts.length - 2; i++) {
|
||||
// pnt1 = pnts[i]
|
||||
// pnt2 = pnts[i + 1]
|
||||
// result = result.concat([...pnt1, 0])
|
||||
// result2.push(
|
||||
// {
|
||||
// lng: pnt1[0],
|
||||
// lat: pnt1[1],
|
||||
// alt: 0
|
||||
// }
|
||||
// )
|
||||
// for (let t = 0; t <= P.Constants.FITTING_COUNT; t++) {
|
||||
// let pnt = P.PlotUtils.getCubicValue(t / P.Constants.FITTING_COUNT, pnt1, normals[i * 2], normals[i * 2 + 1], pnt2)
|
||||
// result = result.concat([...pnt, 0])
|
||||
// result2.push(
|
||||
// {
|
||||
// lng: pnt[0],
|
||||
// lat: pnt[1],
|
||||
// alt: 0
|
||||
// }
|
||||
// )
|
||||
// }
|
||||
// result = result.concat([...pnt2, 0])
|
||||
// result2.push(
|
||||
// {
|
||||
// lng: pnt2[0],
|
||||
// lat: pnt2[1],
|
||||
// alt: 0
|
||||
// }
|
||||
// )
|
||||
// }
|
||||
// this.position = result2
|
||||
// this.points = result
|
||||
// }
|
||||
// }
|
||||
|
||||
calculateVector(v, theta, d) {
|
||||
if (!theta) theta = Math.PI / 2
|
||||
if (!d) d = 1
|
||||
let x_1
|
||||
let x_2
|
||||
let y_1
|
||||
let y_2
|
||||
let v_l
|
||||
let v_r
|
||||
let d_v = Math.sqrt(v.x * v.x + v.y * v.y)
|
||||
if (v.y == 0) {
|
||||
x_1 = x_2 = (d_v * d * Math.cos(theta)) / v.x
|
||||
if (v.x > 0) {
|
||||
y_1 = Math.sqrt(d * d - x_1 * x_1)
|
||||
y_2 = -y_1
|
||||
} else if (v.x < 0) {
|
||||
y_2 = Math.sqrt(d * d - x_1 * x_1)
|
||||
y_1 = -y_2
|
||||
}
|
||||
v_l = { x: x_1, y: y_1 }
|
||||
v_r = { x: x_2, y: y_2 }
|
||||
} else {
|
||||
let n = -v.x / v.y
|
||||
let m = (d * d_v * Math.cos(theta)) / v.y
|
||||
let a = 1 + n * n
|
||||
let b = 2 * n * m
|
||||
let c = m * m - d * d
|
||||
x_1 = (-b - Math.sqrt(b * b - 4 * a * c)) / (2 * a)
|
||||
x_2 = (-b + Math.sqrt(b * b - 4 * a * c)) / (2 * a)
|
||||
y_1 = n * x_1 + m
|
||||
y_2 = n * x_2 + m
|
||||
if (v.y >= 0) {
|
||||
v_l = { x: x_1, y: y_1 }
|
||||
v_r = { x: x_2, y: y_2 }
|
||||
} else if (v.y < 0) {
|
||||
v_l = { x: x_2, y: y_2 }
|
||||
v_r = { x: x_1, y: y_1 }
|
||||
}
|
||||
}
|
||||
return [v_l, v_r]
|
||||
}
|
||||
|
||||
createCloseCardinal(points) {
|
||||
if (points == null || points.length < 3) {
|
||||
return points
|
||||
}
|
||||
//获取起点,作为终点,以闭合曲线。
|
||||
let lastP = points[0]
|
||||
points.push(lastP)
|
||||
//定义传入的点数组,将在点数组中央(每两个点)插入两个控制点
|
||||
let cPoints = points
|
||||
//包含输入点和控制点的数组
|
||||
let cardinalPoints = []
|
||||
//至少三个点以上
|
||||
//这些都是相关资料测出的经验数值
|
||||
//定义张力系数,取值在0<t<0.5
|
||||
let t = 0.4
|
||||
//为端点张力系数因子,取值在0<b<1
|
||||
// let b = 0.5;
|
||||
//误差控制,是一个大于等于0的数,用于三点非常趋近与一条直线时,减少计算量
|
||||
let e = 0.005
|
||||
//传入的点数量,至少有三个,n至少为2
|
||||
let n = cPoints.length - 1
|
||||
//从开始遍历到倒数第二个,其中倒数第二个用于计算起点(终点)的插值控制点
|
||||
for (let k = 0; k <= n - 1; k++) {
|
||||
let p0, p1, p2
|
||||
//计算起点(终点)的左右控制点
|
||||
if (k == n - 1) {
|
||||
//三个基础输入点
|
||||
p0 = cPoints[n - 1]
|
||||
p1 = cPoints[0]
|
||||
p2 = cPoints[1]
|
||||
} else {
|
||||
p0 = cPoints[k]
|
||||
p1 = cPoints[k + 1]
|
||||
p2 = cPoints[k + 2]
|
||||
}
|
||||
//定义p1的左控制点和右控制点
|
||||
let p1l = { x: undefined, y: undefined }
|
||||
let p1r = { x: undefined, y: undefined }
|
||||
//通过p0、p1、p2计算p1点的做控制点p1l和又控制点p1r
|
||||
//计算向量p0_p1和p1_p2
|
||||
let p0_p1 = { x: p1.x - p0.x, y: p1.y - p0.y }
|
||||
let p1_p2 = { x: p2.x - p1.x, y: p2.y - p1.y }
|
||||
//并计算模
|
||||
let d01 = Math.sqrt(p0_p1.x * p0_p1.x + p0_p1.y * p0_p1.y)
|
||||
let d12 = Math.sqrt(p1_p2.x * p1_p2.x + p1_p2.y * p1_p2.y)
|
||||
//向量单位化
|
||||
let p0_p1_1 = { x: p0_p1.x / d01, y: p0_p1.y / d01 }
|
||||
let p1_p2_1 = { x: p1_p2.x / d12, y: p1_p2.y / d12 }
|
||||
//计算向量p0_p1和p1_p2的夹角平分线向量
|
||||
let p0_p1_p2 = { x: p0_p1_1.x + p1_p2_1.x, y: p0_p1_1.y + p1_p2_1.y }
|
||||
//计算向量 p0_p1_p2 的模
|
||||
let d012 = Math.sqrt(p0_p1_p2.x * p0_p1_p2.x + p0_p1_p2.y * p0_p1_p2.y)
|
||||
//单位化向量p0_p1_p2
|
||||
let p0_p1_p2_1 = { x: p0_p1_p2.x / d012, y: p0_p1_p2.y / d012 }
|
||||
//判断p0、p1、p2是否共线,这里判定向量p0_p1和p1_p2的夹角的余弦和1的差值小于e就认为三点共线
|
||||
let cosE_p0p1p2 = (p0_p1_1.x * p1_p2_1.x + p0_p1_1.y * p1_p2_1.y) / 1
|
||||
//共线
|
||||
if (Math.abs(1 - cosE_p0p1p2) < e) {
|
||||
//计算p1l的坐标
|
||||
p1l.x = p1.x - p1_p2_1.x * d01 * t
|
||||
p1l.y = p1.y - p1_p2_1.y * d01 * t
|
||||
//计算p1r的坐标
|
||||
p1r.x = p1.x + p0_p1_1.x * d12 * t
|
||||
p1r.y = p1.y + p0_p1_1.y * d12 * t
|
||||
}
|
||||
//非共线
|
||||
else {
|
||||
//计算p1l的坐标
|
||||
p1l.x = p1.x - p0_p1_p2_1.x * d01 * t
|
||||
p1l.y = p1.y - p0_p1_p2_1.y * d01 * t
|
||||
//计算p1r的坐标
|
||||
p1r.x = p1.x + p0_p1_p2_1.x * d12 * t
|
||||
p1r.y = p1.y + p0_p1_p2_1.y * d12 * t
|
||||
}
|
||||
//记录起点(终点)的左右插值控制点及倒数第二个控制点
|
||||
if (k == n - 1) {
|
||||
cardinalPoints[0] = p1
|
||||
cardinalPoints[1] = p1r
|
||||
cardinalPoints[(n - 2) * 3 + 2 + 3] = p1l
|
||||
cardinalPoints[(n - 2) * 3 + 2 + 4] = cPoints[n]
|
||||
} else {
|
||||
//记录下这三个控制点
|
||||
cardinalPoints[k * 3 + 2 + 0] = p1l
|
||||
cardinalPoints[k * 3 + 2 + 1] = p1
|
||||
cardinalPoints[k * 3 + 2 + 2] = p1r
|
||||
}
|
||||
}
|
||||
return cardinalPoints
|
||||
}
|
||||
|
||||
calculatePointsFBZ3(points, part) {
|
||||
if (!part) part = 20
|
||||
//获取待拆分的点
|
||||
let bezierPts = []
|
||||
let scale = 0.05
|
||||
if (part > 0) {
|
||||
scale = 1 / part
|
||||
}
|
||||
for (let i = 0; i < points.length - 3;) {
|
||||
//起始点
|
||||
let pointS = points[i]
|
||||
//第一个控制点
|
||||
let pointC1 = points[i + 1]
|
||||
//第二个控制点
|
||||
let pointC2 = points[i + 2]
|
||||
//结束点
|
||||
let pointE = points[i + 3]
|
||||
bezierPts.push(pointS)
|
||||
for (let t = 0; t < 1;) {
|
||||
//三次贝塞尔曲线公式
|
||||
let x =
|
||||
(1 - t) * (1 - t) * (1 - t) * pointS.x +
|
||||
3 * t * (1 - t) * (1 - t) * pointC1.x +
|
||||
3 * t * t * (1 - t) * pointC2.x +
|
||||
t * t * t * pointE.x
|
||||
let y =
|
||||
(1 - t) * (1 - t) * (1 - t) * pointS.y +
|
||||
3 * t * (1 - t) * (1 - t) * pointC1.y +
|
||||
3 * t * t * (1 - t) * pointC2.y +
|
||||
t * t * t * pointE.y
|
||||
let point = { x: x, y: y }
|
||||
bezierPts.push(point)
|
||||
t += scale
|
||||
}
|
||||
i += 3
|
||||
if (i >= points.length) {
|
||||
bezierPts.push(pointS)
|
||||
}
|
||||
}
|
||||
return bezierPts
|
||||
}
|
||||
}
|
||||
|
||||
export default DrawAssemble
|
||||
263
src/Draw/drawAttackArrow.js
Normal file
263
src/Draw/drawAttackArrow.js
Normal file
@ -0,0 +1,263 @@
|
||||
/**
|
||||
* @name: drawAttackArrow
|
||||
* @author: Administrator
|
||||
* @date: 2022-06-15 16:38
|
||||
* @description:drawAttackArrow
|
||||
* @update: 2022-06-15 16:38
|
||||
*/
|
||||
import Draw from './draw'
|
||||
import MouseTip from '../MouseTip'
|
||||
import MouseEvent from '../Event'
|
||||
|
||||
export default class DrawAttackArrow extends Draw {
|
||||
constructor(sdk, options = {}) {
|
||||
super(sdk, options)
|
||||
}
|
||||
|
||||
static create_arrow_polygon(that, viewer = that.viewer) {
|
||||
that.entityHasCreated = true
|
||||
let id = that.randomString()
|
||||
viewer.entities.add(
|
||||
new Cesium.Entity({
|
||||
id: id,
|
||||
polygon: {
|
||||
classificationType: Cesium.ClassificationType.BOTH,
|
||||
hierarchy: new Cesium.CallbackProperty((e) => {
|
||||
let arr = that.computeAttackArrow(that.positions)
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
if (isNaN(arr[i].x)) {
|
||||
arr = []
|
||||
break
|
||||
}
|
||||
}
|
||||
return new Cesium.PolygonHierarchy(arr)
|
||||
}, false),
|
||||
material: Cesium.Color.fromCssColorString(that.color),
|
||||
zIndex: 99999999
|
||||
},
|
||||
})
|
||||
)
|
||||
return id
|
||||
}
|
||||
|
||||
start(cb) {
|
||||
if (YJ.Measure.GetMeasureStatus()) {
|
||||
cb('上一次测量未结束')
|
||||
} else {
|
||||
super.start()
|
||||
|
||||
let into
|
||||
YJ.Measure.SetMeasureStatus(true)
|
||||
this.tip = new MouseTip('左键确定,右键结束;CTRL+右键撤销', this.sdk)
|
||||
this.event = new MouseEvent(this.sdk)
|
||||
this.positions = []
|
||||
this.points_ids = [] //存放左键点击时临时添加的point的id
|
||||
let cache_positions = []
|
||||
let isMove = false
|
||||
this.event.mouse_left((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
into = '3D'
|
||||
if (!this.entityHasCreated) {
|
||||
let polyline_id = DrawAttackArrow.create_arrow_polygon(this)
|
||||
this.points_ids.push(polyline_id)
|
||||
}
|
||||
this.points_ids.push(this.create_point(cartesian))
|
||||
cache_positions.push(this.cartesian3Towgs84(cartesian, this.viewer))
|
||||
isMove = false
|
||||
})
|
||||
this.event.mouse_right((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
let c = []
|
||||
if (this.points_ids.length > 2) {
|
||||
let positions = this.viewer.entities.getById(this.points_ids[0]).polygon.hierarchy.getValue().positions
|
||||
positions.forEach(it => {
|
||||
c.push(this.cartesian3Towgs84(it, this.viewer))
|
||||
})
|
||||
}
|
||||
this.end()
|
||||
if (isMove) {
|
||||
this.positions.pop()
|
||||
}
|
||||
cb(null, this.positions, c)
|
||||
})
|
||||
this.event.mouse_move((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
isMove = true
|
||||
this.positions = cache_positions.concat(
|
||||
this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
)
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
movement.endPosition.x,
|
||||
movement.endPosition.y
|
||||
)
|
||||
})
|
||||
this.event.mouse_right_keyboard_ctrl((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
if (this.points_ids.length > 1) {
|
||||
this.remove_entity(this.points_ids.pop()) //移除point
|
||||
cache_positions.pop()
|
||||
}
|
||||
})
|
||||
|
||||
this.event.gesture_pinck_start_keyboard_ctrl(() => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
if (this.points_ids.length > 1) {
|
||||
this.remove_entity(this.points_ids.pop()) //移除point
|
||||
cache_positions.pop()
|
||||
}
|
||||
})
|
||||
|
||||
this.event.gesture_pinck_start((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
let startTime = new Date()
|
||||
this.event.gesture_pinck_end(() => {
|
||||
let endTime = new Date()
|
||||
if (endTime - startTime >= 500) {
|
||||
let c = []
|
||||
if (this.points_ids.length > 2) {
|
||||
let positions = this.viewer.entities.getById(this.points_ids[0]).polygon.hierarchy.getValue().positions
|
||||
positions.forEach(it => {
|
||||
c.push(this.cartesian3Towgs84(it, this.viewer))
|
||||
})
|
||||
}
|
||||
this.end()
|
||||
cb(null, this.positions, c)
|
||||
}
|
||||
else {
|
||||
if (!this.entityHasCreated) {
|
||||
let polyline_id = DrawAttackArrow.create_arrow_polygon(this)
|
||||
this.points_ids.push(polyline_id)
|
||||
}
|
||||
this.points_ids.push(this.create_point(cartesian))
|
||||
cache_positions.push(this.cartesian3Towgs84(cartesian, this.viewer))
|
||||
this.positions = cache_positions.concat(
|
||||
this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
)
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
(movement.position1.x + movement.position2.x) / 2,
|
||||
(movement.position1.y + movement.position2.y) / 2
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
if (!this._is2D && this._sdk2D) {
|
||||
this.event2D = new MouseEvent(this._sdk2D)
|
||||
this.event2D.mouse_left((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
into = '2D'
|
||||
if (!this.entityHasCreated) {
|
||||
let polyline_id = DrawAttackArrow.create_arrow_polygon(this, this._sdk2D.viewer)
|
||||
this.points_ids.push(polyline_id)
|
||||
}
|
||||
this.points_ids.push(this.create_point(cartesian, this._sdk2D.viewer))
|
||||
cache_positions.push(this.cartesian3Towgs84(cartesian, this.viewer))
|
||||
isMove = false
|
||||
})
|
||||
this.event2D.mouse_right((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
let c = []
|
||||
if (this.points_ids.length > 2) {
|
||||
let positions = this.event2D.viewer.entities.getById(this.points_ids[0]).polygon.hierarchy.getValue().positions
|
||||
positions.forEach(it => {
|
||||
c.push(this.cartesian3Towgs84(it, this.viewer))
|
||||
})
|
||||
}
|
||||
this.end()
|
||||
if (isMove) {
|
||||
this.positions.pop()
|
||||
}
|
||||
cb(null, this.positions, c)
|
||||
})
|
||||
this.event2D.mouse_move((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
isMove = true
|
||||
this.positions = cache_positions.concat(
|
||||
this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
)
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
movement.endPosition.x + this.viewer.canvas.width,
|
||||
movement.endPosition.y
|
||||
)
|
||||
})
|
||||
this.event2D.mouse_right_keyboard_ctrl((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
if (this.points_ids.length > 1) {
|
||||
this.remove_entity(this.points_ids.pop()) //移除point
|
||||
cache_positions.pop()
|
||||
}
|
||||
})
|
||||
|
||||
this.event2D.gesture_pinck_start_keyboard_ctrl(() => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
if (this.points_ids.length > 1) {
|
||||
this.remove_entity(this.points_ids.pop()) //移除point
|
||||
cache_positions.pop()
|
||||
}
|
||||
})
|
||||
|
||||
this.event2D.gesture_pinck_start((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
let startTime = new Date()
|
||||
this.event2D.gesture_pinck_end(() => {
|
||||
let endTime = new Date()
|
||||
if (endTime - startTime >= 500) {
|
||||
let c = []
|
||||
if (this.points_ids.length > 2) {
|
||||
let positions = this.viewer.entities.getById(this.points_ids[0]).polygon.hierarchy.getValue().positions
|
||||
positions.forEach(it => {
|
||||
c.push(this.cartesian3Towgs84(it, this.viewer))
|
||||
})
|
||||
}
|
||||
this.end()
|
||||
cb(null, this.positions, c)
|
||||
}
|
||||
else {
|
||||
if (!this.entityHasCreated) {
|
||||
let polyline_id = DrawAttackArrow.create_arrow_polygon(this, this._sdk2D.viewer)
|
||||
this.points_ids.push(polyline_id)
|
||||
}
|
||||
this.points_ids.push(this.create_point(cartesian, this._sdk2D.viewer))
|
||||
cache_positions.push(this.cartesian3Towgs84(cartesian, this.viewer))
|
||||
this.positions = cache_positions.concat(
|
||||
this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
)
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
((movement.position1.x + movement.position2.x) / 2) + this.viewer.canvas.width,
|
||||
(movement.position1.y + movement.position2.y) / 2
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
271
src/Draw/drawCircle.js
Normal file
271
src/Draw/drawCircle.js
Normal file
@ -0,0 +1,271 @@
|
||||
/**
|
||||
* @name: drawCircle
|
||||
* @author: Administrator
|
||||
* @date: 2022-06-15 14:55
|
||||
* @description:drawCircle
|
||||
* @update: 2022-06-15 14:55
|
||||
*/
|
||||
import Draw from './draw'
|
||||
import MouseTip from '../MouseTip'
|
||||
import MouseEvent from '../Event'
|
||||
|
||||
export default class DrawCircle extends Draw {
|
||||
constructor(sdk, options = {}) {
|
||||
super(sdk, options)
|
||||
}
|
||||
|
||||
start(cb) {
|
||||
if (YJ.Measure.GetMeasureStatus()) {
|
||||
cb('上一次测量未结束')
|
||||
} else {
|
||||
super.start()
|
||||
let into
|
||||
YJ.Measure.SetMeasureStatus(true)
|
||||
this.tip = new MouseTip('左键开始,右键取消', this.sdk)
|
||||
this.event = new MouseEvent(this.sdk)
|
||||
let clickNum = 0
|
||||
this.circle_id = this.randomString() //圆id
|
||||
let radius_points = []
|
||||
let cache_points = []
|
||||
let radius = 1 //默认半径
|
||||
let positions = []
|
||||
let center = {}
|
||||
let endpoint = null
|
||||
|
||||
this.event.mouse_left((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
into = '3D'
|
||||
this.tip.set_text('再次左键,完成绘制;右键取消')
|
||||
clickNum++
|
||||
if (clickNum === 1) {
|
||||
this.point_id = this.create_point(cartesian)
|
||||
center = this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
positions = this.createCircle(center, 0.01)
|
||||
cache_points.push(cartesian)
|
||||
createCirclePolygon()
|
||||
}
|
||||
if (clickNum === 2) {
|
||||
radius_points = cache_points.concat(cartesian)
|
||||
endpoint = this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
radius = this.computeDistance([center, endpoint])
|
||||
positions = this.createCircle(center, radius)
|
||||
this.end()
|
||||
cb(null, { center, radius: Number(radius) })
|
||||
}
|
||||
})
|
||||
this.event.mouse_right((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
this.end()
|
||||
cb(false)
|
||||
})
|
||||
this.event.mouse_move((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
movement.endPosition.x,
|
||||
movement.endPosition.y
|
||||
)
|
||||
if (clickNum) {
|
||||
radius_points = cache_points.concat(cartesian)
|
||||
endpoint = this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
radius = this.computeDistance([center, endpoint])
|
||||
positions = this.createCircle(center, radius)
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
this.event.gesture_pinck_start((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
let startTime = new Date()
|
||||
this.event.gesture_pinck_end(() => {
|
||||
let endTime = new Date()
|
||||
if (endTime - startTime >= 500) {
|
||||
this.end()
|
||||
cb(false)
|
||||
}
|
||||
else {
|
||||
this.tip.set_text('再次左键,完成绘制;右键取消')
|
||||
clickNum++
|
||||
if (clickNum === 1) {
|
||||
this.point_id = this.create_point(cartesian)
|
||||
center = this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
cache_points.push(cartesian)
|
||||
createCirclePolygon()
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
(movement.position1.x + movement.position2.x) / 2,
|
||||
(movement.position1.y + movement.position2.y) / 2
|
||||
)
|
||||
}
|
||||
if (clickNum === 2) {
|
||||
radius_points = cache_points.concat(cartesian)
|
||||
endpoint = this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
radius = this.computeDistance([center, endpoint])
|
||||
positions = this.createCircle(center, radius)
|
||||
this.end()
|
||||
cb(null, { center, radius: Number(radius) })
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
if (!this._is2D && this._sdk2D) {
|
||||
this.event2D = new MouseEvent(this._sdk2D)
|
||||
this.event2D.mouse_left((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
into = '2D'
|
||||
this.tip.set_text('再次左键,完成绘制;右键取消')
|
||||
clickNum++
|
||||
if (clickNum === 1) {
|
||||
this.point_id = this.create_point(cartesian, this._sdk2D.viewer)
|
||||
center = this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
positions = this.createCircle(center, 0.01)
|
||||
cache_points.push(cartesian)
|
||||
createCirclePolygon(this._sdk2D.viewer)
|
||||
}
|
||||
if (clickNum === 2) {
|
||||
radius_points = cache_points.concat(cartesian)
|
||||
endpoint = this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
radius = this.computeDistance([center, endpoint])
|
||||
positions = this.createCircle(center, radius)
|
||||
this.end()
|
||||
cb(null, { center, radius: Number(radius) })
|
||||
}
|
||||
})
|
||||
this.event2D.mouse_right((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
this.end()
|
||||
cb(false)
|
||||
})
|
||||
this.event2D.mouse_move((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
movement.endPosition.x + this.viewer.canvas.width,
|
||||
movement.endPosition.y
|
||||
)
|
||||
if (clickNum) {
|
||||
radius_points = cache_points.concat(cartesian)
|
||||
endpoint = this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
radius = this.computeDistance([center, endpoint])
|
||||
positions = this.createCircle(center, radius)
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
this.event2D.gesture_pinck_start((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
let startTime = new Date()
|
||||
this.event2D.gesture_pinck_end(() => {
|
||||
let endTime = new Date()
|
||||
if (endTime - startTime >= 500) {
|
||||
this.end()
|
||||
cb(false)
|
||||
}
|
||||
else {
|
||||
this.tip.set_text('再次左键,完成绘制;右键取消')
|
||||
clickNum++
|
||||
if (clickNum === 1) {
|
||||
this.point_id = this.create_point(cartesian, this._sdk2D.viewer)
|
||||
center = this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
cache_points.push(cartesian)
|
||||
createCirclePolygon(this._sdk2D.viewer)
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
((movement.position1.x + movement.position2.x) / 2) + this.viewer.canvas.width,
|
||||
(movement.position1.y + movement.position2.y) / 2
|
||||
)
|
||||
}
|
||||
if (clickNum === 2) {
|
||||
radius_points = cache_points.concat(cartesian)
|
||||
endpoint = this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
radius = this.computeDistance([center, endpoint])
|
||||
positions = this.createCircle(center, radius)
|
||||
this.end()
|
||||
cb(null, { center, radius: Number(radius) })
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
let that = this
|
||||
|
||||
function createCirclePolygon(viewer = that.viewer) {
|
||||
let a = viewer.entities.add(
|
||||
new Cesium.Entity({
|
||||
id: that.circle_id,
|
||||
position: new Cesium.CallbackProperty((e) => {
|
||||
if (endpoint) {
|
||||
let c = that.computeMidpoint(center, endpoint)
|
||||
return Cesium.Cartesian3.fromDegrees(c.lng, c.lat, endpoint.alt)
|
||||
} else {
|
||||
return Cesium.Cartesian3()
|
||||
}
|
||||
}, false),
|
||||
label: {
|
||||
text: new Cesium.CallbackProperty((e) => {
|
||||
if (radius > 1000) {
|
||||
return '半径:' + (radius / 1000).toFixed(2) + ' 公里'
|
||||
}
|
||||
return '半径:' + radius + ' 米'
|
||||
}, false),
|
||||
font: '20px Microsoft YaHei',
|
||||
distanceDisplayCondition: 10000000,
|
||||
scale: 1,
|
||||
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
||||
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
fillColor: Cesium.Color.fromCssColorString('#f5ce0a'),
|
||||
style: Cesium.LabelStyle.FILL_AND_OUTLINE
|
||||
},
|
||||
polygon: {
|
||||
classificationType: Cesium.ClassificationType.BOTH,
|
||||
hierarchy: new Cesium.CallbackProperty((e) => {
|
||||
return new Cesium.PolygonHierarchy(
|
||||
Cesium.Cartesian3.fromDegreesArray(positions)
|
||||
)
|
||||
}, false),
|
||||
material: Cesium.Color.fromCssColorString(that.color),
|
||||
zIndex: 99999999
|
||||
},
|
||||
polyline: {
|
||||
positions: new Cesium.CallbackProperty((e) => {
|
||||
return radius_points
|
||||
}, false),
|
||||
width: 2,
|
||||
material:
|
||||
Cesium.Color.fromCssColorString('#c1c505').withAlpha(0.5),
|
||||
clampToGround: true,
|
||||
zIndex: 99999999
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end() {
|
||||
this.remove_entity(this.circle_id)
|
||||
this.remove_entity(this.point_id)
|
||||
YJ.Measure.SetMeasureStatus(false)
|
||||
this.tip && this.tip.destroy()
|
||||
this.event && this.event.destroy()
|
||||
this.event2D && this.event2D.destroy()
|
||||
}
|
||||
}
|
||||
244
src/Draw/drawElliptic.js
Normal file
244
src/Draw/drawElliptic.js
Normal file
@ -0,0 +1,244 @@
|
||||
import Draw from './draw'
|
||||
import MouseTip from '../MouseTip'
|
||||
import MouseEvent from '../Event'
|
||||
|
||||
export default class DrawElliptic extends Draw {
|
||||
constructor(sdk, options = {}) {
|
||||
super(sdk, options)
|
||||
}
|
||||
|
||||
start(cb) {
|
||||
if (YJ.Measure.GetMeasureStatus()) {
|
||||
cb('上一次测量未结束')
|
||||
} else {
|
||||
super.start()
|
||||
let into
|
||||
this.entity_ids = []
|
||||
YJ.Measure.SetMeasureStatus(true)
|
||||
this.tip = new MouseTip('左键开始,右键取消', this.sdk)
|
||||
this.event = new MouseEvent(this.sdk)
|
||||
let clickNum = 0
|
||||
this.elliptic_id = this.randomString() //圆id
|
||||
let radius_points = []
|
||||
let cache_points = []
|
||||
let cache_84_position = []
|
||||
let radius = 1 //默认半径
|
||||
let positions = []
|
||||
let center
|
||||
let semiMinorAxis = 0
|
||||
let semiMajorAxis = 0
|
||||
let endpoint = null
|
||||
let distanceAB = 0
|
||||
let distanceAC = 0
|
||||
let distanceBC = 0
|
||||
let bearing = 0
|
||||
|
||||
this.event.mouse_left((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
into = '3D'
|
||||
this.tip.set_text('再次左键,完成绘制;右键取消')
|
||||
clickNum++
|
||||
this.points_ids.push(this.create_point(cartesian))
|
||||
cache_points.push(cartesian)
|
||||
if (clickNum === 1) {
|
||||
cache_points = [cartesian, cartesian, cartesian]
|
||||
let pos84 = this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
center = pos84
|
||||
cache_84_position = [pos84, pos84, pos84]
|
||||
|
||||
calculateElliptic()
|
||||
createEllipticPolygon()
|
||||
}
|
||||
if (clickNum === 2) {
|
||||
cache_points[1] = cartesian
|
||||
cache_points[2] = cartesian
|
||||
let pos84 = this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
cache_84_position[1] = pos84
|
||||
cache_84_position[2] = pos84
|
||||
}
|
||||
if (clickNum >= 3) {
|
||||
this.end()
|
||||
cb(null, { center, bearing, semiMajorAxis, semiMinorAxis })
|
||||
}
|
||||
// if (clickNum === 2) {
|
||||
// radius_points = cache_points.concat(cartesian)
|
||||
// endpoint = this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
// radius = this.computeDistance([center, endpoint])
|
||||
// positions = this.createCircle(center, radius)
|
||||
// this.end()
|
||||
// cb(null, { center, radius: Number(radius) })
|
||||
// }
|
||||
})
|
||||
this.event.mouse_right((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
this.end()
|
||||
cb(false)
|
||||
})
|
||||
this.event.mouse_move((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
movement.endPosition.x,
|
||||
movement.endPosition.y
|
||||
)
|
||||
cache_points[clickNum] = cartesian
|
||||
cache_84_position[clickNum] = this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
if (clickNum !== 0) {
|
||||
calculateElliptic()
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
if (!this._is2D && this._sdk2D) {
|
||||
this.event2D = new MouseEvent(this._sdk2D)
|
||||
this.event2D.mouse_left((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
into = '2D'
|
||||
this.tip.set_text('再次左键,完成绘制;右键取消')
|
||||
clickNum++
|
||||
this.points_ids.push(this.create_point(cartesian, this._sdk2D.viewer))
|
||||
cache_points.push(cartesian)
|
||||
if (clickNum === 1) {
|
||||
cache_points = [cartesian, cartesian, cartesian]
|
||||
let pos84 = this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
center = pos84
|
||||
cache_84_position = [pos84, pos84, pos84]
|
||||
|
||||
calculateElliptic()
|
||||
createEllipticPolygon(this._sdk2D.viewer)
|
||||
}
|
||||
if (clickNum === 2) {
|
||||
cache_points[1] = cartesian
|
||||
cache_points[2] = cartesian
|
||||
let pos84 = this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
cache_84_position[1] = pos84
|
||||
cache_84_position[2] = pos84
|
||||
}
|
||||
if (clickNum >= 3) {
|
||||
this.end()
|
||||
cb(null, { center, bearing, semiMajorAxis, semiMinorAxis })
|
||||
}
|
||||
// if (clickNum === 2) {
|
||||
// radius_points = cache_points.concat(cartesian)
|
||||
// endpoint = this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
// radius = this.computeDistance([center, endpoint])
|
||||
// positions = this.createCircle(center, radius)
|
||||
// this.end()
|
||||
// cb(null, { center, radius: Number(radius) })
|
||||
// }
|
||||
})
|
||||
this.event2D.mouse_right((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
this.end()
|
||||
cb(false)
|
||||
})
|
||||
this.event2D.mouse_move((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
movement.endPosition.x + this.viewer.canvas.width,
|
||||
movement.endPosition.y
|
||||
)
|
||||
cache_points[clickNum] = cartesian
|
||||
cache_84_position[clickNum] = this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
if (clickNum !== 0) {
|
||||
calculateElliptic()
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
let that = this
|
||||
|
||||
function calculateElliptic() {
|
||||
let pointA = Cesium.Cartesian3.fromDegrees(cache_84_position[0].lng, cache_84_position[0].lat);
|
||||
let pointB = Cesium.Cartesian3.fromDegrees(cache_84_position[1].lng, cache_84_position[1].lat);
|
||||
let pointC = Cesium.Cartesian3.fromDegrees(cache_84_position[2].lng, cache_84_position[2].lat);
|
||||
if (clickNum === 1) {
|
||||
distanceAB = Cesium.Cartesian3.distance(pointA, pointB);
|
||||
semiMajorAxis = distanceAB
|
||||
semiMinorAxis = semiMajorAxis / 2;
|
||||
|
||||
let start = { x: center.lng, y: center.lat }
|
||||
let end = { x: cache_84_position[1].lng, y: cache_84_position[1].lat }
|
||||
|
||||
let rad = Math.PI / 180,
|
||||
lat1 = start.y * rad,
|
||||
lat2 = end.y * rad,
|
||||
lon1 = start.x * rad,
|
||||
lon2 = end.x * rad;
|
||||
const a = Math.sin(lon2 - lon1) * Math.cos(lat2);
|
||||
const b =
|
||||
Math.cos(lat1) * Math.sin(lat2) -
|
||||
Math.sin(lat1) * Math.cos(lat2) * Math.cos(lon2 - lon1);
|
||||
const radians = Math.atan2(a, b)
|
||||
const degrees = radians % (2 * Math.PI);
|
||||
bearing = 450 - ((degrees * 180) / Math.PI < 0
|
||||
? 360 + (degrees * 180) / Math.PI
|
||||
: (degrees * 180) / Math.PI);
|
||||
}
|
||||
if (clickNum === 2) {
|
||||
distanceAC = Cesium.Cartesian3.distance(pointA, pointC);
|
||||
distanceBC = Cesium.Cartesian3.distance(pointB, pointC);
|
||||
|
||||
let point1 = turf.point([cache_84_position[0].lng, cache_84_position[0].lat]);
|
||||
let point2 = turf.point([cache_84_position[1].lng, cache_84_position[1].lat]);
|
||||
let point3 = turf.point([cache_84_position[2].lng, cache_84_position[2].lat]);
|
||||
const bearing1 = turf.rhumbBearing(point1, point2);
|
||||
const bearing2 = turf.rhumbBearing(point2, point3);
|
||||
const angleDiff = Math.abs(bearing1 - bearing2);
|
||||
let finalAngle = angleDiff > 180 ? 360 - angleDiff : angleDiff;
|
||||
finalAngle = 180 - finalAngle
|
||||
|
||||
semiMinorAxis = distanceBC * Math.sin(Cesium.Math.toRadians(finalAngle));
|
||||
}
|
||||
}
|
||||
|
||||
function createEllipticPolygon(viewer = that.viewer) {
|
||||
viewer.entities.add(
|
||||
new Cesium.Entity({
|
||||
id: that.elliptic_id,
|
||||
position: Cesium.Cartesian3.fromDegrees(center.lng, center.lat),
|
||||
ellipse: {
|
||||
semiMinorAxis: new Cesium.CallbackProperty((e) => {
|
||||
return semiMinorAxis
|
||||
}, false),
|
||||
semiMajorAxis: new Cesium.CallbackProperty((e) => {
|
||||
return semiMajorAxis
|
||||
}, false),
|
||||
granularity: Cesium.Math.toRadians(0.1),
|
||||
rotation: new Cesium.CallbackProperty((e) => {
|
||||
return Cesium.Math.toRadians(bearing)
|
||||
}, false),
|
||||
material: Cesium.Color.fromCssColorString(that.color),
|
||||
zIndex: 99999999
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end() {
|
||||
this.remove_entity(this.elliptic_id)
|
||||
this.points_ids.forEach((id) => {
|
||||
this.remove_entity(id)
|
||||
})
|
||||
YJ.Measure.SetMeasureStatus(false)
|
||||
this.tip && this.tip.destroy()
|
||||
this.event && this.event.destroy()
|
||||
this.event2D && this.event2D.destroy()
|
||||
}
|
||||
}
|
||||
273
src/Draw/drawPincerArrow.js
Normal file
273
src/Draw/drawPincerArrow.js
Normal file
@ -0,0 +1,273 @@
|
||||
/**
|
||||
* @name: drawPincerArrow
|
||||
* @author: Administrator
|
||||
* @date: 2022-06-15 17:12
|
||||
* @description:drawPincerArrow
|
||||
* @update: 2022-06-15 17:12
|
||||
*/
|
||||
import Draw from './draw'
|
||||
import MouseTip from '../MouseTip'
|
||||
import MouseEvent from '../Event'
|
||||
|
||||
export default class DrawPincerArrow extends Draw {
|
||||
constructor(sdk, options = {}) {
|
||||
super(sdk, options)
|
||||
}
|
||||
|
||||
static create_arrow_polygon(that, viewer = that.viewer) {
|
||||
that.entityHasCreated = true
|
||||
let id = that.randomString()
|
||||
viewer.entities.add(
|
||||
new Cesium.Entity({
|
||||
id: id,
|
||||
polygon: {
|
||||
classificationType: Cesium.ClassificationType.BOTH,
|
||||
hierarchy: new Cesium.CallbackProperty((e) => {
|
||||
let arr = that.computePincerArrow(that.positions)
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
if (isNaN(arr[i].x)) {
|
||||
arr = []
|
||||
break
|
||||
}
|
||||
}
|
||||
return new Cesium.PolygonHierarchy(arr)
|
||||
}, false),
|
||||
material: Cesium.Color.fromCssColorString(that.color),
|
||||
zIndex: 99999999
|
||||
},
|
||||
})
|
||||
)
|
||||
return id
|
||||
}
|
||||
|
||||
start(cb) {
|
||||
if (YJ.Measure.GetMeasureStatus()) {
|
||||
cb('上一次测量未结束')
|
||||
} else {
|
||||
super.start()
|
||||
let into
|
||||
YJ.Measure.SetMeasureStatus(true)
|
||||
this.tip = new MouseTip('左键确定,右键取消;CTRL+右键撤销', this.sdk)
|
||||
this.event = new MouseEvent(this.sdk)
|
||||
this.positions = []
|
||||
this.points_ids = [] //存放左键点击时临时添加的point的id
|
||||
let cache_positions = []
|
||||
this.event.mouse_left((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
into = '3D'
|
||||
if (!this.entityHasCreated) {
|
||||
let polyline_id = DrawPincerArrow.create_arrow_polygon(this)
|
||||
this.points_ids.push(polyline_id)
|
||||
}
|
||||
this.points_ids.push(this.create_point(cartesian))
|
||||
cache_positions.push(this.cartesian3Towgs84(cartesian, this.viewer))
|
||||
if (cache_positions.length === 5) {
|
||||
let c = []
|
||||
if (this.points_ids.length > 2) {
|
||||
let positions = this.viewer.entities.getById(this.points_ids[0]).polygon.hierarchy.getValue().positions
|
||||
positions.forEach(it => {
|
||||
c.push(this.cartesian3Towgs84(it, this.viewer))
|
||||
})
|
||||
}
|
||||
this.end()
|
||||
cb(null, cache_positions, c)
|
||||
}
|
||||
})
|
||||
this.event.mouse_right((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
this.end()
|
||||
cb('取消绘制')
|
||||
})
|
||||
this.event.mouse_move((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
this.positions = cache_positions.concat(
|
||||
this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
)
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
movement.endPosition.x,
|
||||
movement.endPosition.y
|
||||
)
|
||||
})
|
||||
this.event.mouse_right_keyboard_ctrl((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
if (this.points_ids.length > 1) {
|
||||
this.remove_entity(this.points_ids.pop()) //移除point
|
||||
cache_positions.pop()
|
||||
}
|
||||
})
|
||||
|
||||
this.event.gesture_pinck_start_keyboard_ctrl(() => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
if (this.points_ids.length > 1) {
|
||||
this.remove_entity(this.points_ids.pop()) //移除point
|
||||
cache_positions.pop()
|
||||
this.positions = cache_positions.concat(
|
||||
this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
this.event.gesture_pinck_start((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
let startTime = new Date()
|
||||
this.event.gesture_pinck_end(() => {
|
||||
let endTime = new Date()
|
||||
if (endTime - startTime >= 500) {
|
||||
this.end()
|
||||
cb('取消绘制')
|
||||
}
|
||||
else {
|
||||
if (!this.entityHasCreated) {
|
||||
let polyline_id = DrawPincerArrow.create_arrow_polygon(this)
|
||||
this.points_ids.push(polyline_id)
|
||||
}
|
||||
this.points_ids.push(this.create_point(cartesian))
|
||||
cache_positions.push(this.cartesian3Towgs84(cartesian, this.viewer))
|
||||
this.positions = cache_positions.concat(
|
||||
this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
)
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
(movement.position1.x + movement.position2.x) / 2,
|
||||
(movement.position1.y + movement.position2.y) / 2
|
||||
)
|
||||
if (cache_positions.length === 5) {
|
||||
let c = []
|
||||
if (this.points_ids.length > 2) {
|
||||
let positions = this.viewer.entities.getById(this.points_ids[0]).polygon.hierarchy.getValue().positions
|
||||
positions.forEach(it => {
|
||||
c.push(this.cartesian3Towgs84(it, this.viewer))
|
||||
})
|
||||
}
|
||||
this.end()
|
||||
cb(null, cache_positions, c)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
if (!this._is2D && this._sdk2D) {
|
||||
this.event2D = new MouseEvent(this._sdk2D)
|
||||
this.event2D.mouse_left((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
into = '2D'
|
||||
if (!this.entityHasCreated) {
|
||||
let polyline_id = DrawPincerArrow.create_arrow_polygon(this, this._sdk2D.viewer)
|
||||
this.points_ids.push(polyline_id)
|
||||
}
|
||||
this.points_ids.push(this.create_point(cartesian, this._sdk2D.viewer))
|
||||
cache_positions.push(this.cartesian3Towgs84(cartesian, this.viewer))
|
||||
if (cache_positions.length === 5) {
|
||||
let c = []
|
||||
if (this.points_ids.length > 2) {
|
||||
let positions = this.event2D.viewer.entities.getById(this.points_ids[0]).polygon.hierarchy.getValue().positions
|
||||
positions.forEach(it => {
|
||||
c.push(this.cartesian3Towgs84(it, this.viewer))
|
||||
})
|
||||
}
|
||||
this.end()
|
||||
cb(null, cache_positions, c)
|
||||
}
|
||||
})
|
||||
this.event2D.mouse_right((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
this.end()
|
||||
cb('取消绘制')
|
||||
})
|
||||
this.event2D.mouse_move((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
this.positions = cache_positions.concat(
|
||||
this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
)
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
movement.endPosition.x + this.viewer.canvas.width,
|
||||
movement.endPosition.y
|
||||
)
|
||||
})
|
||||
this.event2D.mouse_right_keyboard_ctrl((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
if (this.points_ids.length > 1) {
|
||||
this.remove_entity(this.points_ids.pop()) //移除point
|
||||
cache_positions.pop()
|
||||
}
|
||||
})
|
||||
|
||||
this.event2D.gesture_pinck_start_keyboard_ctrl(() => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
if (this.points_ids.length > 1) {
|
||||
this.remove_entity(this.points_ids.pop()) //移除point
|
||||
cache_positions.pop()
|
||||
this.positions = cache_positions.concat(
|
||||
this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
this.event2D.gesture_pinck_start((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
let startTime = new Date()
|
||||
this.event2D.gesture_pinck_end(() => {
|
||||
let endTime = new Date()
|
||||
if (endTime - startTime >= 500) {
|
||||
this.end()
|
||||
cb('取消绘制')
|
||||
}
|
||||
else {
|
||||
if (!this.entityHasCreated) {
|
||||
let polyline_id = DrawPincerArrow.create_arrow_polygon(this, this._sdk2D.viewer)
|
||||
this.points_ids.push(polyline_id)
|
||||
}
|
||||
this.points_ids.push(this.create_point(cartesian, this._sdk2D.viewer))
|
||||
cache_positions.push(this.cartesian3Towgs84(cartesian, this.viewer))
|
||||
this.positions = cache_positions.concat(
|
||||
this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
)
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
((movement.position1.x + movement.position2.x) / 2) + this.viewer.canvas.width,
|
||||
(movement.position1.y + movement.position2.y) / 2
|
||||
)
|
||||
if (cache_positions.length === 5) {
|
||||
let c = []
|
||||
if (this.points_ids.length > 2) {
|
||||
let positions = this.event2D.viewer.entities.getById(this.points_ids[0]).polygon.hierarchy.getValue().positions
|
||||
positions.forEach(it => {
|
||||
c.push(this.cartesian3Towgs84(it, this.viewer))
|
||||
})
|
||||
}
|
||||
this.end()
|
||||
cb(null, cache_positions, c)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
116
src/Draw/drawPoint.js
Normal file
116
src/Draw/drawPoint.js
Normal file
@ -0,0 +1,116 @@
|
||||
import MouseTip from '../MouseTip'
|
||||
import MouseEvent from '../Event'
|
||||
import Draw from "./draw";
|
||||
|
||||
|
||||
class DrawPoint extends Draw {
|
||||
/**
|
||||
* @constructor
|
||||
* @desc 获取坐标点
|
||||
* */
|
||||
constructor(sdk, options = {}, is2D = false) {
|
||||
super(sdk, options, is2D)
|
||||
}
|
||||
|
||||
/**
|
||||
* @desc 开始动态获取坐标点
|
||||
* @method start
|
||||
* @param cb {function} 回调函数
|
||||
* @memberOf DrawPoint
|
||||
* @example draw.start((err,position)=>{
|
||||
*
|
||||
* })
|
||||
* */
|
||||
|
||||
start(cb) {
|
||||
if (YJ.Measure.GetMeasureStatus()) {
|
||||
cb('上一次测量未结束')
|
||||
} else {
|
||||
let car = undefined
|
||||
YJ.Measure.SetMeasureStatus(true)
|
||||
this.tip = new MouseTip('左键确定,右键结束;', this.sdk)
|
||||
this.event = new MouseEvent(this.sdk)
|
||||
this.event.mouse_left((movement, cartesian) => {
|
||||
this.end()
|
||||
let p = this.cartesian3Towgs84(car || cartesian, this.viewer)
|
||||
cb(null, p, Cesium)
|
||||
})
|
||||
this.event.mouse_right((movement, cartesian) => {
|
||||
this.end()
|
||||
cb(false)
|
||||
})
|
||||
this.event.mouse_move((movement, cartesian) => {
|
||||
car = cartesian
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
movement.endPosition.x,
|
||||
movement.endPosition.y
|
||||
)
|
||||
})
|
||||
|
||||
this.event.gesture_pinck_start((movement, cartesian) => {
|
||||
let startTime = new Date()
|
||||
this.event.gesture_pinck_end(() => {
|
||||
let endTime = new Date()
|
||||
if (endTime - startTime >= 500) {
|
||||
this.end()
|
||||
cb(false)
|
||||
}
|
||||
else {
|
||||
this.end()
|
||||
let p = this.cartesian3Towgs84(car || cartesian, this.viewer)
|
||||
cb(null, p)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
|
||||
if (!this._is2D && this._sdk2D) {
|
||||
this.event2D = new MouseEvent(this._sdk2D)
|
||||
this.event2D.mouse_left((movement, cartesian) => {
|
||||
this.end()
|
||||
let p = this.cartesian3Towgs84(car || cartesian, this.viewer)
|
||||
cb(null, p, Cesium)
|
||||
})
|
||||
this.event2D.mouse_right((movement, cartesian) => {
|
||||
this.end()
|
||||
cb(false)
|
||||
})
|
||||
this.event2D.mouse_move((movement, cartesian) => {
|
||||
car = cartesian
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
movement.endPosition.x + this.viewer.canvas.width,
|
||||
movement.endPosition.y
|
||||
)
|
||||
})
|
||||
|
||||
this.event2D.gesture_pinck_start((movement, cartesian) => {
|
||||
let startTime = new Date()
|
||||
this.event2D.gesture_pinck_end(() => {
|
||||
let endTime = new Date()
|
||||
if (endTime - startTime >= 500) {
|
||||
this.end()
|
||||
cb(false)
|
||||
}
|
||||
else {
|
||||
this.end()
|
||||
let p = this.cartesian3Towgs84(car || cartesian, this.viewer)
|
||||
cb(null, p)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end() {
|
||||
YJ.Measure.SetMeasureStatus(false)
|
||||
this.event && this.event.destroy()
|
||||
this.event2D && this.event2D.destroy()
|
||||
this.tip && this.tip.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
export default DrawPoint
|
||||
276
src/Draw/drawPolygon.js
Normal file
276
src/Draw/drawPolygon.js
Normal file
@ -0,0 +1,276 @@
|
||||
import MouseTip from '../MouseTip'
|
||||
import MouseEvent from '../Event'
|
||||
import Draw from './draw'
|
||||
|
||||
/**
|
||||
* @extends Draw*/
|
||||
class DrawPolygon extends Draw {
|
||||
/**
|
||||
* @constructor
|
||||
* @param [options] {object} 面属性
|
||||
* @param [options.color=rgba(185,14,14,0.58)] {object} 线属性
|
||||
|
||||
* */
|
||||
constructor(sdk, options = {}) {
|
||||
super(sdk, options)
|
||||
this.polygonHasCreated = false
|
||||
}
|
||||
|
||||
static create_polygon(that, viewer = that.viewer) {
|
||||
that.polygonHasCreated = true
|
||||
let id = that.randomString()
|
||||
viewer.entities.add(
|
||||
new Cesium.Entity({
|
||||
id: id,
|
||||
polygon: {
|
||||
classificationType: Cesium.ClassificationType.BOTH,
|
||||
hierarchy: new Cesium.CallbackProperty((e) => {
|
||||
return new Cesium.PolygonHierarchy(that.positions)
|
||||
}),
|
||||
material: Cesium.Color.fromCssColorString(that.color),
|
||||
zIndex: 99999999
|
||||
},
|
||||
polyline: {
|
||||
positions: new Cesium.CallbackProperty((e) => {
|
||||
return that.positions.concat(that.positions[0])
|
||||
}),
|
||||
width: 2,
|
||||
material: Cesium.Color.fromCssColorString('#c1c505').withAlpha(0.5),
|
||||
clampToGround: true,
|
||||
zIndex: 99999999
|
||||
},
|
||||
})
|
||||
)
|
||||
return id
|
||||
}
|
||||
|
||||
/**
|
||||
* @desc 开始动态绘制面
|
||||
* @method start
|
||||
* @param cb {function} 回调函数
|
||||
* @memberOf DrawPolygon
|
||||
* @example draw.start((err,positions)=>{
|
||||
*
|
||||
* })
|
||||
* */
|
||||
start(cb) {
|
||||
if (YJ.Measure.GetMeasureStatus()) {
|
||||
cb('上一次测量未结束')
|
||||
} else {
|
||||
this.polygonHasCreated = false
|
||||
super.start()
|
||||
YJ.Measure.SetMeasureStatus(true)
|
||||
let into
|
||||
this.tip = new MouseTip('左键确定,右键结束;CTRL+右键撤销', this.sdk)
|
||||
this.event = new MouseEvent(this.sdk)
|
||||
this.positions = []
|
||||
this.points_ids = [] //存放左键点击时临时添加的point的id
|
||||
let cache_positions = []
|
||||
let cache_84_position = []
|
||||
this.event.mouse_left((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
into = '3D'
|
||||
this.positions = cache_positions.concat({ ...cartesian })
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
movement.position.x,
|
||||
movement.position.y
|
||||
)
|
||||
if (!this.polygonHasCreated) {
|
||||
let polyline_id = DrawPolygon.create_polygon(this)
|
||||
this.points_ids.push(polyline_id)
|
||||
}
|
||||
cache_positions.push(cartesian)
|
||||
// console.log(cache_positions)
|
||||
cache_84_position.push(this.cartesian3Towgs84(cartesian, this.viewer))
|
||||
// console.log(this.cartesian3Towgs84(cartesian))
|
||||
this.points_ids.push(this.create_point(cartesian))
|
||||
})
|
||||
this.event.mouse_right((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
// let positions = []
|
||||
// console.log(cache_positions)
|
||||
// cache_positions.forEach((item) => {
|
||||
// let p = this.cartesian3Towgs84(item)
|
||||
// console.log(item)
|
||||
// positions.push(p)
|
||||
// })
|
||||
cb(null, cache_84_position)
|
||||
this.end()
|
||||
})
|
||||
this.event.mouse_move((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
this.positions = cache_positions.concat({ ...cartesian })
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
movement.endPosition.x,
|
||||
movement.endPosition.y
|
||||
)
|
||||
})
|
||||
this.event.mouse_right_keyboard_ctrl((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
if (this.points_ids.length > 1) {
|
||||
this.remove_entity(this.points_ids.pop()) //移除point
|
||||
cache_positions.pop()
|
||||
cache_84_position.pop()
|
||||
}
|
||||
})
|
||||
|
||||
this.event.gesture_pinck_start_keyboard_ctrl(() => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
if (this.points_ids.length > 1) {
|
||||
this.remove_entity(this.points_ids.pop()) //移除point
|
||||
cache_positions.pop()
|
||||
cache_84_position.pop()
|
||||
this.positions = cache_positions.concat(cartesian)
|
||||
}
|
||||
})
|
||||
|
||||
this.event.gesture_pinck_start((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
let startTime = new Date()
|
||||
this.event.gesture_pinck_end(() => {
|
||||
let endTime = new Date()
|
||||
if (endTime - startTime >= 500) {
|
||||
cb(null, cache_84_position)
|
||||
this.end()
|
||||
}
|
||||
else {
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
(movement.position1.x + movement.position2.x) / 2,
|
||||
(movement.position1.y + movement.position2.y) / 2
|
||||
)
|
||||
if (!this.polygonHasCreated) {
|
||||
let polyline_id = DrawPolygon.create_polygon(this)
|
||||
this.points_ids.push(polyline_id)
|
||||
}
|
||||
cache_positions.push(cartesian)
|
||||
// console.log(cache_positions)
|
||||
cache_84_position.push(this.cartesian3Towgs84(cartesian, this.viewer))
|
||||
// console.log(this.cartesian3Towgs84(cartesian))
|
||||
this.points_ids.push(this.create_point(cartesian))
|
||||
this.positions = cache_positions.concat(cartesian)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
if (!this._is2D && this._sdk2D) {
|
||||
this.event2D = new MouseEvent(this._sdk2D)
|
||||
this.event2D.mouse_left((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
into = '2D'
|
||||
this.positions = cache_positions.concat({ ...cartesian })
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
movement.position.x + this.viewer.canvas.width,
|
||||
movement.position.y
|
||||
)
|
||||
if (!this.polygonHasCreated) {
|
||||
let polyline_id = DrawPolygon.create_polygon(this, this._sdk2D.viewer)
|
||||
this.points_ids.push(polyline_id)
|
||||
}
|
||||
cache_positions.push(cartesian)
|
||||
// console.log(cache_positions)
|
||||
cache_84_position.push(this.cartesian3Towgs84(cartesian, this.viewer))
|
||||
// console.log(this.cartesian3Towgs84(cartesian))
|
||||
this.points_ids.push(this.create_point(cartesian, this._sdk2D.viewer))
|
||||
})
|
||||
this.event2D.mouse_right((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
// let positions = []
|
||||
// console.log(cache_positions)
|
||||
// cache_positions.forEach((item) => {
|
||||
// let p = this.cartesian3Towgs84(item)
|
||||
// console.log(item)
|
||||
// positions.push(p)
|
||||
// })
|
||||
cb(null, cache_84_position)
|
||||
this.end()
|
||||
})
|
||||
this.event2D.mouse_move((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
this.positions = cache_positions.concat({ ...cartesian })
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
movement.endPosition.x + this.viewer.canvas.width,
|
||||
movement.endPosition.y
|
||||
)
|
||||
})
|
||||
this.event2D.mouse_right_keyboard_ctrl((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
if (this.points_ids.length > 1) {
|
||||
this.remove_entity(this.points_ids.pop()) //移除point
|
||||
cache_positions.pop()
|
||||
cache_84_position.pop()
|
||||
}
|
||||
})
|
||||
|
||||
this.event2D.gesture_pinck_start_keyboard_ctrl(() => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
if (this.points_ids.length > 1) {
|
||||
this.remove_entity(this.points_ids.pop()) //移除point
|
||||
cache_positions.pop()
|
||||
cache_84_position.pop()
|
||||
this.positions = cache_positions.concat(cartesian)
|
||||
}
|
||||
})
|
||||
|
||||
this.event2D.gesture_pinck_start((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
let startTime = new Date()
|
||||
this.event2D.gesture_pinck_end(() => {
|
||||
let endTime = new Date()
|
||||
if (endTime - startTime >= 500) {
|
||||
cb(null, cache_84_position)
|
||||
this.end()
|
||||
}
|
||||
else {
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
((movement.position1.x + movement.position2.x) / 2) + this.viewer.canvas.width,
|
||||
(movement.position1.y + movement.position2.y) / 2
|
||||
)
|
||||
if (!this.polygonHasCreated) {
|
||||
let polyline_id = DrawPolygon.create_polygon(this, this._sdk2D.viewer)
|
||||
this.points_ids.push(polyline_id)
|
||||
}
|
||||
cache_positions.push(cartesian)
|
||||
// console.log(cache_positions)
|
||||
cache_84_position.push(this.cartesian3Towgs84(cartesian, this.viewer))
|
||||
// console.log(this.cartesian3Towgs84(cartesian))
|
||||
this.points_ids.push(this.create_point(cartesian, this._sdk2D.viewer))
|
||||
this.positions = cache_positions.concat(cartesian)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default DrawPolygon
|
||||
348
src/Draw/drawPolyline.js
Normal file
348
src/Draw/drawPolyline.js
Normal file
@ -0,0 +1,348 @@
|
||||
import MouseTip from '../MouseTip'
|
||||
import MouseEvent from '../Event'
|
||||
import Draw from './draw'
|
||||
|
||||
/**
|
||||
* @extends Draw
|
||||
*/
|
||||
|
||||
class DrawPolyline extends Draw {
|
||||
/**
|
||||
* @constructor
|
||||
* @param [options] {object} 线属性
|
||||
* @param [options.color=rgba(185,14,14,0.58)] {object} 线属性
|
||||
*
|
||||
* */
|
||||
constructor(sdk, options = {}) {
|
||||
super(sdk, options)
|
||||
this.options.curve = options.curve || false
|
||||
let number = Number(options.number)
|
||||
if (!isNaN(number)) {
|
||||
if (number < 2) {
|
||||
this.options.number = 2
|
||||
}
|
||||
else {
|
||||
this.options.number = number
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.options.number = Infinity
|
||||
}
|
||||
}
|
||||
|
||||
static create_polyline(that, viewer = that.viewer) {
|
||||
that.entityHasCreated = true
|
||||
let id = that.randomString()
|
||||
viewer.entities.add(
|
||||
new Cesium.Entity({
|
||||
id: id,
|
||||
polyline: {
|
||||
positions: new Cesium.CallbackProperty(() => {
|
||||
if (that.options.curve) {
|
||||
let positions = that.smoothHandle(that.positions)
|
||||
return positions
|
||||
}
|
||||
else {
|
||||
return that.positions
|
||||
}
|
||||
}, false),
|
||||
width: 5,
|
||||
material: Cesium.Color.fromCssColorString(that.color),
|
||||
clampToGround: true,
|
||||
zIndex: 99999999
|
||||
}
|
||||
})
|
||||
)
|
||||
return id
|
||||
}
|
||||
|
||||
// 平滑处理
|
||||
smoothHandle(positions) {
|
||||
if (positions.length > 1) {
|
||||
let newPositions = []
|
||||
let time = []
|
||||
for (let i = 0; i < positions.length; i++) {
|
||||
time.push(i / (positions.length - 1))
|
||||
}
|
||||
let spline = new Cesium.CatmullRomSpline({
|
||||
times: time,
|
||||
points: positions
|
||||
});
|
||||
let length = positions.length * 20
|
||||
for (let i = 0; i <= length; i++) {
|
||||
let cartesian3 = spline.evaluate(i / length);
|
||||
newPositions.push(cartesian3);
|
||||
}
|
||||
return newPositions
|
||||
}
|
||||
else {
|
||||
return positions
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @desc 开始动态获绘制线
|
||||
* @method start
|
||||
* @param cb {function} 回调函数
|
||||
* @memberOf DrawPolyline
|
||||
* @example draw.start((err,positions)=>{
|
||||
*
|
||||
* })
|
||||
* */
|
||||
start(cb) {
|
||||
if (YJ.Measure.GetMeasureStatus()) {
|
||||
cb('上一次测量未结束')
|
||||
} else {
|
||||
super.start()
|
||||
let into
|
||||
YJ.Measure.SetMeasureStatus(true)
|
||||
this.tip = new MouseTip('左键确定,右键结束;CTRL+右键撤销', this.sdk)
|
||||
this.event = new MouseEvent(this.sdk)
|
||||
this.positions = []
|
||||
this.points_ids = [] //存放左键点击时临时添加的point的id
|
||||
|
||||
let cache_positions = []
|
||||
let car = undefined
|
||||
this.event.mouse_left((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
into = '3D'
|
||||
this.positions = cache_positions.concat(cartesian)
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
movement.position.x,
|
||||
movement.position.y
|
||||
)
|
||||
if (!this.entityHasCreated) {
|
||||
let polyline_id = DrawPolyline.create_polyline(this, this.viewer)
|
||||
this.points_ids.push(polyline_id)
|
||||
}
|
||||
cache_positions.push(cartesian)
|
||||
this.points_ids.push(this.create_point(cartesian, this.viewer))
|
||||
|
||||
if (cache_positions.length >= this.options.number) {
|
||||
let positions = []
|
||||
cache_positions.forEach((item) => {
|
||||
positions.push(this.cartesian3Towgs84(item, this.viewer))
|
||||
})
|
||||
let smoothPos
|
||||
if (this.options.curve) {
|
||||
let pos = this.smoothHandle(cache_positions)
|
||||
smoothPos = []
|
||||
for (let i = 0; i < pos.length; i++) {
|
||||
smoothPos[i] = this.cartesian3Towgs84(pos[i], this.viewer)
|
||||
}
|
||||
}
|
||||
cb(null, positions, smoothPos)
|
||||
this.end()
|
||||
}
|
||||
})
|
||||
this.event.mouse_right((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
let positions = []
|
||||
cache_positions.forEach((item) => {
|
||||
positions.push(this.cartesian3Towgs84(item, this.viewer))
|
||||
})
|
||||
let smoothPos
|
||||
if (this.options.curve) {
|
||||
let pos = this.smoothHandle(cache_positions)
|
||||
smoothPos = []
|
||||
for (let i = 0; i < pos.length; i++) {
|
||||
smoothPos[i] = this.cartesian3Towgs84(pos[i], this.viewer)
|
||||
}
|
||||
}
|
||||
cb(null, positions, smoothPos)
|
||||
this.end()
|
||||
})
|
||||
this.event.mouse_move((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
this.positions = cache_positions.concat(cartesian)
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
movement.endPosition.x,
|
||||
movement.endPosition.y
|
||||
)
|
||||
})
|
||||
this.event.mouse_right_keyboard_ctrl((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
if (this.points_ids.length > 1) {
|
||||
this.remove_entity(this.points_ids.pop()) //移除point
|
||||
cache_positions.pop()
|
||||
}
|
||||
})
|
||||
|
||||
this.event.gesture_pinck_start_keyboard_ctrl(() => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
if (this.points_ids.length > 1) {
|
||||
this.remove_entity(this.points_ids.pop()) //移除point
|
||||
cache_positions.pop()
|
||||
this.positions = cache_positions.concat(cartesian)
|
||||
}
|
||||
})
|
||||
|
||||
this.event.gesture_pinck_start((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
let startTime = new Date()
|
||||
this.event.gesture_pinck_end(() => {
|
||||
let endTime = new Date()
|
||||
if (endTime - startTime >= 500) {
|
||||
let positions = []
|
||||
cache_positions.forEach((item) => {
|
||||
positions.push(this.cartesian3Towgs84(item, this.viewer))
|
||||
})
|
||||
let smoothPos
|
||||
if (this.options.curve) {
|
||||
let pos = this.smoothHandle(cache_positions)
|
||||
smoothPos = []
|
||||
for (let i = 0; i < pos.length; i++) {
|
||||
smoothPos[i] = this.cartesian3Towgs84(pos[i], this.viewer)
|
||||
}
|
||||
}
|
||||
cb(null, positions, smoothPos)
|
||||
this.end()
|
||||
}
|
||||
else {
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
(movement.position1.x + movement.position2.x) / 2,
|
||||
(movement.position1.y + movement.position2.y) / 2
|
||||
)
|
||||
if (!this.entityHasCreated) {
|
||||
let polyline_id = DrawPolyline.create_polyline(this, this.viewer)
|
||||
this.points_ids.push(polyline_id)
|
||||
}
|
||||
cache_positions.push(cartesian)
|
||||
this.points_ids.push(this.create_point(cartesian, this.viewer))
|
||||
this.positions = cache_positions.concat(cartesian)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
if (!this._is2D && this._sdk2D) {
|
||||
this.event2D = new MouseEvent(this._sdk2D)
|
||||
this.event2D.mouse_left((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
into = '2D'
|
||||
this.positions = cache_positions.concat(cartesian)
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
movement.position.x + this.viewer.canvas.width,
|
||||
movement.position.y
|
||||
)
|
||||
if (!this.entityHasCreated) {
|
||||
let polyline_id = DrawPolyline.create_polyline(this, this._sdk2D.viewer)
|
||||
this.points_ids.push(polyline_id)
|
||||
}
|
||||
cache_positions.push(cartesian)
|
||||
this.points_ids.push(this.create_point(cartesian, this._sdk2D.viewer))
|
||||
})
|
||||
this.event2D.mouse_right((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
let positions = []
|
||||
cache_positions.forEach((item) => {
|
||||
positions.push(this.cartesian3Towgs84(item, this.viewer))
|
||||
})
|
||||
let smoothPos
|
||||
if (this.options.curve) {
|
||||
let pos = this.smoothHandle(cache_positions)
|
||||
smoothPos = []
|
||||
for (let i = 0; i < pos.length; i++) {
|
||||
smoothPos[i] = this.cartesian3Towgs84(pos[i], this.viewer)
|
||||
}
|
||||
}
|
||||
cb(null, positions, smoothPos)
|
||||
this.end()
|
||||
})
|
||||
this.event2D.mouse_move((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
this.positions = cache_positions.concat(cartesian)
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
movement.endPosition.x + this.viewer.canvas.width,
|
||||
movement.endPosition.y
|
||||
)
|
||||
})
|
||||
this.event2D.mouse_right_keyboard_ctrl((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
if (this.points_ids.length > 1) {
|
||||
this.remove_entity(this.points_ids.pop()) //移除point
|
||||
cache_positions.pop()
|
||||
}
|
||||
})
|
||||
|
||||
this.event2D.gesture_pinck_start_keyboard_ctrl(() => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
if (this.points_ids.length > 1) {
|
||||
this.remove_entity(this.points_ids.pop()) //移除point
|
||||
cache_positions.pop()
|
||||
this.positions = cache_positions.concat(cartesian)
|
||||
}
|
||||
})
|
||||
|
||||
this.event2D.gesture_pinck_start((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
let startTime = new Date()
|
||||
this.event2D.gesture_pinck_end(() => {
|
||||
let endTime = new Date()
|
||||
if (endTime - startTime >= 500) {
|
||||
let positions = []
|
||||
cache_positions.forEach((item) => {
|
||||
positions.push(this.cartesian3Towgs84(item, this.viewer))
|
||||
})
|
||||
let smoothPos
|
||||
if (this.options.curve) {
|
||||
let pos = this.smoothHandle(cache_positions)
|
||||
smoothPos = []
|
||||
for (let i = 0; i < pos.length; i++) {
|
||||
smoothPos[i] = this.cartesian3Towgs84(pos[i], this.viewer)
|
||||
}
|
||||
}
|
||||
cb(null, positions, smoothPos)
|
||||
this.end()
|
||||
}
|
||||
else {
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
((movement.position1.x + movement.position2.x) / 2) + this.viewer.canvas.width,
|
||||
(movement.position1.y + movement.position2.y) / 2
|
||||
)
|
||||
if (!this.entityHasCreated) {
|
||||
let polyline_id = DrawPolyline.create_polyline(this, this._sdk2D.viewer)
|
||||
this.points_ids.push(polyline_id)
|
||||
}
|
||||
cache_positions.push(cartesian)
|
||||
this.points_ids.push(this.create_point(cartesian, this._sdk2D.viewer))
|
||||
this.positions = cache_positions.concat(cartesian)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default DrawPolyline
|
||||
278
src/Draw/drawRect.js
Normal file
278
src/Draw/drawRect.js
Normal file
@ -0,0 +1,278 @@
|
||||
import MouseTip from '../MouseTip'
|
||||
import MouseEvent from '../Event'
|
||||
import Draw from './draw'
|
||||
|
||||
/**
|
||||
* @extends Draw*/
|
||||
class DrawRect extends Draw {
|
||||
/**
|
||||
* @constructor
|
||||
* @param [options] {object} 面属性
|
||||
* @param [options.color=rgba(185,14,14,0.58)] {object} 线属性
|
||||
|
||||
* */
|
||||
constructor(sdk, options = {}) {
|
||||
super(sdk, options)
|
||||
this.rhumb = options.rhumb
|
||||
this.polygonHasCreated = false
|
||||
this.rect = []
|
||||
this.rectObj = []
|
||||
this.entity = null
|
||||
}
|
||||
|
||||
static create_polygon(that, viewer = that.viewer) {
|
||||
let id = that.randomString()
|
||||
viewer.entities.add(
|
||||
(this.entity = new Cesium.Entity({
|
||||
id: id,
|
||||
polygon: {
|
||||
// classificationType: Cesium.ClassificationType.BOTH,
|
||||
hierarchy: new Cesium.CallbackProperty(e => {
|
||||
return new Cesium.PolygonHierarchy(
|
||||
Cesium.Cartesian3.fromDegreesArray(that.rect)
|
||||
)
|
||||
},false),
|
||||
material: Cesium.Color.fromCssColorString(that.color),
|
||||
arcType: that.rhumb ? Cesium.ArcType.RHUMB : Cesium.ArcType.GEODESIC,
|
||||
zIndex: 99999999
|
||||
}
|
||||
}))
|
||||
)
|
||||
return id
|
||||
}
|
||||
|
||||
/**
|
||||
* @desc 开始动态绘制面
|
||||
* @method start
|
||||
* @param cb {function} 回调函数
|
||||
* @memberOf DrawRect
|
||||
* @example draw.start((err,positions)=>{
|
||||
*
|
||||
* })
|
||||
* */
|
||||
start(cb) {
|
||||
let that = this
|
||||
if (YJ.Measure.GetMeasureStatus()) {
|
||||
cb('上一次测量未结束')
|
||||
} else {
|
||||
super.start()
|
||||
let into
|
||||
YJ.Measure.SetMeasureStatus(true)
|
||||
this.tip = new MouseTip('左键确定,右键取消', that.sdk)
|
||||
this.event = new MouseEvent(that.sdk)
|
||||
this.positions = []
|
||||
this.points_ids = [] //存放左键点击时临时添加的point的id
|
||||
let cache_positions = []
|
||||
let cache_84_position = []
|
||||
let cnt = 0
|
||||
let firstPoint = null
|
||||
let secondtPoint = null
|
||||
this.event.mouse_left((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
into = '3D'
|
||||
cnt++
|
||||
let wgs84 = this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
|
||||
if (!this.polygonHasCreated) {
|
||||
this.polygonHasCreated = true
|
||||
let polyline_id = DrawRect.create_polygon(this)
|
||||
this.points_ids.push(polyline_id)
|
||||
firstPoint = wgs84
|
||||
}
|
||||
|
||||
if (cnt == 2) {
|
||||
secondtPoint = wgs84
|
||||
this.end()
|
||||
cb(null, that.rectObj, [firstPoint, secondtPoint])
|
||||
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
this.event.mouse_right((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
this.end()
|
||||
cb('取消', '')
|
||||
})
|
||||
this.event.mouse_move((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
movement.endPosition.x,
|
||||
movement.endPosition.y
|
||||
)
|
||||
if (cnt == 1) {
|
||||
let wgs84 = this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
this.calrect(firstPoint, wgs84)
|
||||
}
|
||||
})
|
||||
|
||||
this.event.gesture_pinck_start((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
let startTime = new Date()
|
||||
this.event.gesture_pinck_end(() => {
|
||||
let endTime = new Date()
|
||||
if (endTime - startTime >= 500) {
|
||||
cb('取消', '')
|
||||
this.end()
|
||||
}
|
||||
else {
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
(movement.position1.x + movement.position2.x) / 2,
|
||||
(movement.position1.y + movement.position2.y) / 2
|
||||
)
|
||||
cnt++
|
||||
let wgs84 = this.cartesian3Towgs84(cartesian)
|
||||
|
||||
if (!this.polygonHasCreated) {
|
||||
this.polygonHasCreated = true
|
||||
let polyline_id = DrawRect.create_polygon(this)
|
||||
this.points_ids.push(polyline_id)
|
||||
firstPoint = wgs84
|
||||
}
|
||||
|
||||
if (cnt == 2) {
|
||||
this.calrect(firstPoint, wgs84)
|
||||
secondtPoint = wgs84
|
||||
this.end()
|
||||
cb(null, that.rectObj, [firstPoint, secondtPoint])
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
if (!this._is2D && this._sdk2D) {
|
||||
this.event2D = new MouseEvent(this._sdk2D)
|
||||
this.event2D.mouse_left((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
into = '2D'
|
||||
cnt++
|
||||
let wgs84 = this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
|
||||
if (!this.polygonHasCreated) {
|
||||
this.polygonHasCreated = true
|
||||
let polyline_id = DrawRect.create_polygon(this, this._sdk2D.viewer)
|
||||
this.points_ids.push(polyline_id)
|
||||
firstPoint = wgs84
|
||||
}
|
||||
|
||||
if (cnt == 2) {
|
||||
secondtPoint = wgs84
|
||||
this.end()
|
||||
cb(null, that.rectObj, [firstPoint, secondtPoint])
|
||||
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
this.event2D.mouse_right((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
this.end()
|
||||
cb('取消', '')
|
||||
})
|
||||
this.event2D.mouse_move((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
movement.endPosition.x + this.viewer.canvas.width,
|
||||
movement.endPosition.y
|
||||
)
|
||||
if (cnt == 1) {
|
||||
let wgs84 = this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
this.calrect(firstPoint, wgs84)
|
||||
}
|
||||
})
|
||||
|
||||
this.event2D.gesture_pinck_start((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
let startTime = new Date()
|
||||
this.event2D.gesture_pinck_end(() => {
|
||||
let endTime = new Date()
|
||||
if (endTime - startTime >= 500) {
|
||||
cb('取消', '')
|
||||
this.end()
|
||||
}
|
||||
else {
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
((movement.position1.x + movement.position2.x) / 2) + this.viewer.canvas.width,
|
||||
(movement.position1.y + movement.position2.y) / 2
|
||||
)
|
||||
cnt++
|
||||
let wgs84 = this.cartesian3Towgs84(cartesian)
|
||||
|
||||
if (!this.polygonHasCreated) {
|
||||
this.polygonHasCreated = true
|
||||
let polyline_id = DrawRect.create_polygon(this, this._sdk2D.viewer)
|
||||
this.points_ids.push(polyline_id)
|
||||
firstPoint = wgs84
|
||||
}
|
||||
|
||||
if (cnt == 2) {
|
||||
this.calrect(firstPoint, wgs84)
|
||||
secondtPoint = wgs84
|
||||
this.end()
|
||||
cb(null, that.rectObj, [firstPoint, secondtPoint])
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
calrect(firstPoint, secondPoint) {
|
||||
let positions = []
|
||||
let arr = []
|
||||
let arr2 = []
|
||||
positions.push(
|
||||
[firstPoint.lng, firstPoint.lat, firstPoint.alt],
|
||||
[secondPoint.lng, secondPoint.lat, secondPoint.alt]
|
||||
)
|
||||
let bboxPolygon
|
||||
if (positions.length === 2) {
|
||||
let line = turf.lineString(positions)
|
||||
let bbox = turf.bbox(line)
|
||||
bboxPolygon = turf.bboxPolygon(bbox)
|
||||
}
|
||||
if (bboxPolygon) {
|
||||
// console.log('bboxPolygon',bboxPolygon.geometry.coordinates[0])
|
||||
bboxPolygon.geometry.coordinates[0].forEach(item => {
|
||||
arr.push(item[0])
|
||||
arr.push(item[1])
|
||||
let obj = {
|
||||
lng: item[0],
|
||||
lat: item[1],
|
||||
alt: firstPoint.alt
|
||||
}
|
||||
arr2.push(obj)
|
||||
})
|
||||
this.rect = [...arr]
|
||||
this.rectObj = [...arr2]
|
||||
this.rectObj.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default DrawRect
|
||||
268
src/Draw/drawSector.js
Normal file
268
src/Draw/drawSector.js
Normal file
@ -0,0 +1,268 @@
|
||||
import MouseTip from '../MouseTip'
|
||||
import MouseEvent from '../Event'
|
||||
import Draw from './draw'
|
||||
|
||||
/**
|
||||
* @extends Draw*/
|
||||
class DrawSector extends Draw {
|
||||
constructor(sdk, options = {}) {
|
||||
super(sdk, options)
|
||||
}
|
||||
|
||||
/**
|
||||
* @desc 开始动态绘制面
|
||||
* @method start
|
||||
* @param cb {function} 回调函数
|
||||
* @memberOf DrawRect
|
||||
* @example draw.start((err,positions)=>{
|
||||
*
|
||||
* })
|
||||
* */
|
||||
start(cb) {
|
||||
let that = this
|
||||
if (YJ.Measure.GetMeasureStatus()) {
|
||||
cb('上一次测量未结束')
|
||||
} else {
|
||||
super.start()
|
||||
let into
|
||||
YJ.Measure.SetMeasureStatus(true)
|
||||
this.tip = new MouseTip('左键确认,右键取消', that.sdk)
|
||||
this.event = new MouseEvent(that.sdk)
|
||||
this._sector_id = null; //扇形
|
||||
this._positions = []; //活动点
|
||||
this.points_ids = []; //脏数据
|
||||
this._entities_sector = []; //脏数据
|
||||
this._radius = 0; //半径
|
||||
this._startAngle = 0; //起始角度
|
||||
this._endAngle = 0; //结束角度
|
||||
this.event.mouse_left((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
into = '3D'
|
||||
// if(that._positions.length == 3) return
|
||||
|
||||
if (this._positions.length < 3) {
|
||||
this.points_ids.push(this.create_point(cartesian));
|
||||
this._positions.push(this.cartesian3Towgs84(cartesian, this.viewer));
|
||||
}
|
||||
else {
|
||||
this.end()
|
||||
cb(null, { center: this._positions[0], radius: this._radius, startAngle: this._startAngle, endAngle: this._endAngle })
|
||||
}
|
||||
if (this._positions.length === 2) {
|
||||
let pointA = Cesium.Cartesian3.fromDegrees(this._positions[0].lng, this._positions[0].lat, this._positions[0].alt);
|
||||
let pointB = cartesian;
|
||||
this._radius = Cesium.Cartesian3.distance(pointA, pointB);
|
||||
}
|
||||
})
|
||||
this.event.mouse_move((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
movement.endPosition.x,
|
||||
movement.endPosition.y
|
||||
)
|
||||
if (this._positions.length < 2) return;
|
||||
if (this._positions.length == 2) {
|
||||
this._positions.push(this.cartesian3Towgs84(cartesian, this.viewer));
|
||||
}
|
||||
if (this._positions.length == 3) {
|
||||
this._positions.pop();
|
||||
this._positions.push(this.cartesian3Towgs84(cartesian, this.viewer));
|
||||
if (!Cesium.defined(this._sector_id)) {
|
||||
this._sector_id = this.createsector();
|
||||
this.points_ids.push(this._sector_id);
|
||||
}
|
||||
|
||||
let options = that.calculateAangle(that._positions)
|
||||
that._startAngle = options.angle1;
|
||||
that._endAngle = options.angle2;
|
||||
}
|
||||
|
||||
})
|
||||
this.event.mouse_right((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
this.end()
|
||||
cb(null)
|
||||
})
|
||||
if (!this._is2D && this._sdk2D) {
|
||||
this.event2D = new MouseEvent(this._sdk2D)
|
||||
this.event2D.mouse_left((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
into = '2D'
|
||||
// if(that._positions.length == 3) return
|
||||
|
||||
if (this._positions.length < 3) {
|
||||
this.points_ids.push(this.create_point(cartesian, this._sdk2D.viewer));
|
||||
this._positions.push(this.cartesian3Towgs84(cartesian, this.viewer));
|
||||
}
|
||||
else {
|
||||
this.end()
|
||||
cb(null, { center: this._positions[0], radius: this._radius, startAngle: this._startAngle, endAngle: this._endAngle })
|
||||
}
|
||||
if (this._positions.length === 2) {
|
||||
let pointA = Cesium.Cartesian3.fromDegrees(this._positions[0].lng, this._positions[0].lat, this._positions[0].alt);
|
||||
let pointB = cartesian;
|
||||
this._radius = Cesium.Cartesian3.distance(pointA, pointB);
|
||||
}
|
||||
})
|
||||
this.event2D.mouse_move((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
movement.endPosition.x + this.viewer.canvas.width,
|
||||
movement.endPosition.y
|
||||
)
|
||||
if (this._positions.length < 2) return;
|
||||
if (this._positions.length == 2) {
|
||||
this._positions.push(this.cartesian3Towgs84(cartesian, this.viewer));
|
||||
}
|
||||
if (this._positions.length == 3) {
|
||||
this._positions.pop();
|
||||
this._positions.push(this.cartesian3Towgs84(cartesian, this.viewer));
|
||||
if (!Cesium.defined(this._sector_id)) {
|
||||
this._sector_id = this.createsector(this._sdk2D.viewer);
|
||||
this.points_ids.push(this._sector_id);
|
||||
}
|
||||
|
||||
let options = that.calculateAangle(that._positions)
|
||||
that._startAngle = options.angle1;
|
||||
that._endAngle = options.angle2;
|
||||
}
|
||||
|
||||
})
|
||||
this.event2D.mouse_right((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
this.end()
|
||||
cb(null)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//创建直线扇形
|
||||
createsector(viewer = this.viewer) {
|
||||
// console.log(this._positions)
|
||||
let that = this;
|
||||
let angle
|
||||
let hierarchy = new Cesium.CallbackProperty(
|
||||
() => {
|
||||
let pList = that.calSector(that._positions[0], that._radius, that._startAngle, that._endAngle)
|
||||
return new Cesium.PolygonHierarchy(pList);
|
||||
})
|
||||
// let text = new Cesium.CallbackProperty(
|
||||
// () => {
|
||||
// angle = that._endAngle - that._startAngle
|
||||
// if (angle < 0) {
|
||||
// angle = 360 + angle
|
||||
// }
|
||||
// return angle.toFixed(2) + '°';
|
||||
// })
|
||||
let id = that.randomString()
|
||||
let arrowEntity = viewer.entities.add({
|
||||
id: id,
|
||||
position: Cesium.Cartesian3.fromDegrees(that._positions[0].lng, that._positions[0].lat),
|
||||
// label: {
|
||||
// text,
|
||||
// font: "24px Helvetica",
|
||||
// fillColor: Cesium.Color.SKYBLUE,
|
||||
// outlineColor: Cesium.Color.BLACK,
|
||||
// outlineWidth: 2,
|
||||
// style: Cesium.LabelStyle.FILL_AND_OUTLINE,
|
||||
// pixelOffset: new Cesium.Cartesian2(0, -12),
|
||||
// horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
||||
// verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
// disableDepthTestDistance: Number.POSITIVE_INFINITY
|
||||
// },
|
||||
polygon: {
|
||||
hierarchy,
|
||||
show: true,
|
||||
fill: true,
|
||||
clampToGround: true,
|
||||
material: Cesium.Color.fromCssColorString(that.color),
|
||||
zIndex: 99999999
|
||||
}
|
||||
}
|
||||
)
|
||||
that._entities_sector.push(arrowEntity);
|
||||
return id
|
||||
}
|
||||
|
||||
cartesianToLatlng(cartesian) {
|
||||
let latlng = this.viewer.scene.globe.ellipsoid.cartesianToCartographic(cartesian);
|
||||
let lat = Cesium.Math.toDegrees(latlng.latitude);
|
||||
let lng = Cesium.Math.toDegrees(latlng.longitude);
|
||||
return [lng, lat];
|
||||
}
|
||||
|
||||
/**
|
||||
* 经纬度坐标转墨卡托坐标
|
||||
*/
|
||||
// 墨卡托坐标系:展开地球,赤道作为x轴,向东为x轴正方,本初子午线作为y轴,向北为y轴正方向。
|
||||
// 数字20037508.34是地球赤道周长的一半:地球半径6378137米,赤道周长2*PI*r = 2 * 20037508.3427892,墨卡托坐标x轴区间[-20037508.3427892,20037508.3427892]
|
||||
lonLatToMercator(Latlng) {
|
||||
let E = Latlng[0];
|
||||
let N = Latlng[1];
|
||||
let x = E * 20037508.34 / 180;
|
||||
let y = Math.log(Math.tan((90 + N) * Math.PI / 360)) / (Math.PI / 180);
|
||||
y = y * 20037508.34 / 180;
|
||||
return [x, y]
|
||||
}
|
||||
|
||||
WebMercator2lonLat(mercator) {
|
||||
let x = mercator[0] / 20037508.34 * 180;
|
||||
let ly = mercator[1] / 20037508.34 * 180;
|
||||
let y = 180 / Math.PI * (2 * Math.atan(Math.exp(ly * Math.PI / 180)) - Math.PI / 2)
|
||||
return [x, y];
|
||||
}
|
||||
|
||||
//计算角度
|
||||
calculateAangle(arr) {
|
||||
function getAangle(start, end) {
|
||||
let rad = Math.PI / 180,
|
||||
lat1 = start.y * rad,
|
||||
lat2 = end.y * rad,
|
||||
lon1 = start.x * rad,
|
||||
lon2 = end.x * rad;
|
||||
const a = Math.sin(lon2 - lon1) * Math.cos(lat2);
|
||||
const b =
|
||||
Math.cos(lat1) * Math.sin(lat2) -
|
||||
Math.sin(lat1) * Math.cos(lat2) * Math.cos(lon2 - lon1);
|
||||
const radians = Math.atan2(a, b)
|
||||
const degrees = radians % (2 * Math.PI);
|
||||
let bearing = 450 - ((degrees * 180) / Math.PI < 0
|
||||
? 360 + (degrees * 180) / Math.PI
|
||||
: (degrees * 180) / Math.PI) - 90;
|
||||
return 360 - (bearing % 360)
|
||||
}
|
||||
|
||||
let center = arr[0]
|
||||
let pos84_1 = arr[1]
|
||||
let pos84_2 = arr[2]
|
||||
|
||||
let start = { x: center.lng, y: center.lat }
|
||||
let end1 = { x: pos84_1.lng, y: pos84_1.lat }
|
||||
let end2 = { x: pos84_2.lng, y: pos84_2.lat }
|
||||
|
||||
let angle1 = getAangle(start, end1)
|
||||
let angle2 = getAangle(start, end2)
|
||||
|
||||
return {
|
||||
angle1,
|
||||
angle2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default DrawSector
|
||||
262
src/Draw/drawStraightArrow.js
Normal file
262
src/Draw/drawStraightArrow.js
Normal file
@ -0,0 +1,262 @@
|
||||
import MouseTip from '../MouseTip'
|
||||
import MouseEvent from '../Event'
|
||||
import Draw from './draw'
|
||||
|
||||
const transformCartesianToWGS84 = cartesian => {
|
||||
let ellipsoid = Cesium.Ellipsoid.WGS84
|
||||
let cartographic = ellipsoid.cartesianToCartographic(cartesian)
|
||||
const x = Cesium.Math.toDegrees(cartographic.longitude)
|
||||
const y = Cesium.Math.toDegrees(cartographic.latitude)
|
||||
const z = cartographic.height
|
||||
return { x, y, z }
|
||||
}
|
||||
|
||||
/**
|
||||
* @extends Draw*/
|
||||
class DrawStraightArrow extends Draw {
|
||||
/**
|
||||
* @constructor
|
||||
* @param sdk
|
||||
* @param [options] {object} 面属性
|
||||
* @param [options.color=rgba(185,14,14,0.58)] {object} 线属性
|
||||
|
||||
* */
|
||||
constructor(sdk, options = {}) {
|
||||
super(sdk, options)
|
||||
this.points = null
|
||||
this.polygonHasCreated = false
|
||||
}
|
||||
|
||||
static polygon(that, viewer = that.viewer) {
|
||||
let id = that.randomString()
|
||||
return viewer.entities.add(
|
||||
new Cesium.Entity({
|
||||
name: 'ArrowPolygon',
|
||||
id,
|
||||
polygon: {
|
||||
hierarchy: new Cesium.CallbackProperty(e => {
|
||||
let arr = that.computeStraightArrow(that.positions)
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
if (isNaN(arr[i].x)) {
|
||||
arr = []
|
||||
break
|
||||
}
|
||||
}
|
||||
return new Cesium.PolygonHierarchy(arr)
|
||||
}, false),
|
||||
material: Cesium.Color.fromCssColorString(that.color),
|
||||
outline: true,
|
||||
outlineColor: Cesium.Color.GREEN,
|
||||
zIndex: 99999999
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @desc 开始动态绘制面
|
||||
* @method start
|
||||
* @param cb {function} 回调函数
|
||||
* @memberOf DrawPolygon
|
||||
* @example draw.start((err,positions)=>{
|
||||
*
|
||||
* })
|
||||
* */
|
||||
start(cb) {
|
||||
let that = this
|
||||
// eslint-disable-next-line no-undef
|
||||
if (YJ.Measure.GetMeasureStatus()) {
|
||||
cb('上一次测量未结束')
|
||||
} else {
|
||||
super.start()
|
||||
// eslint-disable-next-line no-undef
|
||||
let into
|
||||
YJ.Measure.SetMeasureStatus(true)
|
||||
this.tip = new MouseTip('左键确定,右键取消;', that.sdk)
|
||||
this.event = new MouseEvent(that.sdk)
|
||||
this.positions = []
|
||||
this.points_ids = [] //存放左键点击时临时添加的point的id
|
||||
let cache_positions = []
|
||||
let cache_84_position = []
|
||||
this.anchorpoints = []
|
||||
this.event.mouse_left((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
into = '3D'
|
||||
if (!cartesian || this.anchorpoints[0]===cartesian) return
|
||||
this.anchorpoints.push(cartesian)
|
||||
|
||||
let p = this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
p.lng = Number(p.lng.toFixed(8))
|
||||
p.lat = Number(p.lat.toFixed(8))
|
||||
if(cache_positions[0] && (p.lng === cache_positions[0].lng && p.lat === cache_positions[0].lat)) return;
|
||||
cache_positions.push(p)
|
||||
this.positions.push(p)
|
||||
// console.log(this.cartesian3Towgs84(cartesian))
|
||||
this.points_ids.push(this.create_point(cartesian))
|
||||
if (this.points_ids.length === 2) {
|
||||
let array = [cache_positions[0], cache_positions[1]]
|
||||
cb(null, array)
|
||||
this.end()
|
||||
}
|
||||
})
|
||||
this.event.mouse_move((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
movement.endPosition.x,
|
||||
movement.endPosition.y
|
||||
)
|
||||
if (!cartesian || this.points_ids.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
let p = this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
this.positions = [this.positions[0], p];
|
||||
if (this.points_ids.length === 1 && !Cesium.defined(this.arrowPolygon)) {
|
||||
this.arrowPolygon = DrawStraightArrow.polygon(this)
|
||||
}
|
||||
})
|
||||
this.event.mouse_right((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
cb(null)
|
||||
this.end()
|
||||
})
|
||||
|
||||
this.event.gesture_pinck_start((movement, cartesian) => {
|
||||
if(into === '2D') {
|
||||
return
|
||||
}
|
||||
let startTime = new Date()
|
||||
this.event.gesture_pinck_end(() => {
|
||||
let endTime = new Date()
|
||||
if (endTime - startTime >= 500) {
|
||||
this.end()
|
||||
cb(false)
|
||||
}
|
||||
else {
|
||||
if (this.anchorpoints.length === 2) {
|
||||
this.anchorpoints.push(cartesian)
|
||||
cb(null, this.positions)
|
||||
this.end()
|
||||
}
|
||||
else {
|
||||
if (!cartesian || Cesium.defined(this.arrowPolygon)) return
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
(movement.position1.x + movement.position2.x) / 2,
|
||||
(movement.position1.y + movement.position2.y) / 2
|
||||
)
|
||||
this.anchorpoints.push(cartesian)
|
||||
this.arrowPolygon = DrawStraightArrow.polygon(this)
|
||||
cache_positions.push(this.cartesian3Towgs84(cartesian))
|
||||
// console.log(this.cartesian3Towgs84(cartesian))
|
||||
this.points_ids.push(this.create_point(cartesian))
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
if (!this._is2D && this._sdk2D) {
|
||||
this.event2D = new MouseEvent(this._sdk2D)
|
||||
this.event2D.mouse_left((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
into = '2D'
|
||||
if (!cartesian || this.anchorpoints[0]===cartesian) return
|
||||
this.anchorpoints.push(cartesian)
|
||||
|
||||
let p = this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
p.lng = Number(p.lng.toFixed(8))
|
||||
p.lat = Number(p.lat.toFixed(8))
|
||||
if(cache_positions[0] && (p.lng === cache_positions[0].lng && p.lat === cache_positions[0].lat)) return;
|
||||
cache_positions.push(p)
|
||||
this.positions.push(p)
|
||||
// console.log(this.cartesian3Towgs84(cartesian))
|
||||
this.points_ids.push(this.create_point(cartesian, this._sdk2D.viewer))
|
||||
if (this.points_ids.length === 2) {
|
||||
let array = [cache_positions[0], cache_positions[1]]
|
||||
cb(null, array)
|
||||
this.end()
|
||||
}
|
||||
})
|
||||
this.event2D.mouse_move((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
movement.endPosition.x + this.viewer.canvas.width,
|
||||
movement.endPosition.y
|
||||
)
|
||||
if (!cartesian || this.points_ids.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
let p = this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
this.positions = [this.positions[0], p];
|
||||
if (this.points_ids.length === 1 && !Cesium.defined(this.arrowPolygon)) {
|
||||
this.arrowPolygon = DrawStraightArrow.polygon(this, this._sdk2D.viewer)
|
||||
}
|
||||
})
|
||||
this.event2D.mouse_right((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
cb(null)
|
||||
this.end()
|
||||
})
|
||||
|
||||
this.event2D.gesture_pinck_start((movement, cartesian) => {
|
||||
if(into === '3D') {
|
||||
return
|
||||
}
|
||||
let startTime = new Date()
|
||||
this.event2D.gesture_pinck_end(() => {
|
||||
let endTime = new Date()
|
||||
if (endTime - startTime >= 500) {
|
||||
this.end()
|
||||
cb(false)
|
||||
}
|
||||
else {
|
||||
if (this.anchorpoints.length === 2) {
|
||||
this.anchorpoints.push(cartesian)
|
||||
cb(null, this.positions)
|
||||
this.end()
|
||||
}
|
||||
else {
|
||||
if (!cartesian || Cesium.defined(this.arrowPolygon)) return
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
(movement.position1.x + movement.position2.x) / 2 + this.viewer.canvas.width,
|
||||
(movement.position1.y + movement.position2.y) / 2
|
||||
)
|
||||
this.anchorpoints.push(cartesian)
|
||||
this.arrowPolygon = DrawStraightArrow.polygon(this, this._sdk2D.viewer)
|
||||
cache_positions.push(this.cartesian3Towgs84(cartesian))
|
||||
// console.log(this.cartesian3Towgs84(cartesian))
|
||||
this.points_ids.push(this.create_point(cartesian, this._sdk2D.viewer))
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end() {
|
||||
super.end();
|
||||
this.viewer.entities.remove(this.arrowPolygon)
|
||||
if (!this._is2D && this._sdk2D) {
|
||||
this._sdk2D.viewer.entities.remove(this.arrowPolygon)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default DrawStraightArrow
|
||||
196
src/Event/index.js
Normal file
196
src/Event/index.js
Normal file
@ -0,0 +1,196 @@
|
||||
/**
|
||||
* @name: index
|
||||
* @author: Administrator
|
||||
* @date: 2022-06-14 14:44
|
||||
* @description:index
|
||||
* @update: 2022-06-14 14:44
|
||||
*/
|
||||
|
||||
export default class MouseEvent {
|
||||
constructor(sdk) {
|
||||
this.sdk = sdk
|
||||
this.viewer = sdk.viewer
|
||||
this.handler = new Cesium.ScreenSpaceEventHandler(
|
||||
this.viewer.canvas
|
||||
)
|
||||
}
|
||||
|
||||
/*事件*/
|
||||
mouse_left(cb) {
|
||||
// //左键点击事件
|
||||
this.handler && this.handler.setInputAction((movement) => {
|
||||
let cartesian = this.getcartesian(movement)
|
||||
// cartesian = this.earth.czm.viewer.scene.pickPosition(movement.position)
|
||||
// if (!cartesian) {
|
||||
// cartesian = this.viewer.scene.camera.pickEllipsoid(
|
||||
// movement.position,
|
||||
// this.viewer.scene.globe.ellipsoid
|
||||
// )
|
||||
// }
|
||||
// if (cartesian) {
|
||||
// cb(movement, cartesian)
|
||||
// }
|
||||
if (cartesian) {
|
||||
cb(movement, cartesian)
|
||||
}
|
||||
}, Cesium.ScreenSpaceEventType.LEFT_CLICK)
|
||||
}
|
||||
|
||||
mouse_left_down(cb) {
|
||||
// //左键按下事件
|
||||
this.handler && this.handler.setInputAction((movement) => {
|
||||
let cartesian = this.getcartesian(movement)
|
||||
if (cartesian) {
|
||||
cb(movement, cartesian)
|
||||
}
|
||||
}, Cesium.ScreenSpaceEventType.LEFT_DOWN)
|
||||
}
|
||||
mouse_left_up(cb) {
|
||||
// //左键抬起事件
|
||||
this.handler && this.handler.setInputAction((movement) => {
|
||||
let cartesian = this.getcartesian(movement)
|
||||
if (cartesian) {
|
||||
cb(movement, cartesian)
|
||||
}
|
||||
}, Cesium.ScreenSpaceEventType.LEFT_UP)
|
||||
}
|
||||
|
||||
mouse_move(cb, allowNull = false) {
|
||||
this.handler && this.handler.setInputAction((movement) => {
|
||||
let cartesian = this.getcartesian(movement)
|
||||
|
||||
if (cartesian || allowNull) {
|
||||
cb(movement, cartesian)
|
||||
}
|
||||
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
|
||||
}
|
||||
|
||||
mouse_right(cb, allowNull = false) {
|
||||
this.handler && this.handler.setInputAction((movement) => {
|
||||
let cartesian = this.getcartesian(movement)
|
||||
if (cartesian || allowNull) {
|
||||
cb(movement, cartesian)
|
||||
}
|
||||
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK)
|
||||
}
|
||||
|
||||
mouse_right_down(cb, allowNull = false) {
|
||||
this.handler && this.handler.setInputAction((movement) => {
|
||||
let cartesian = this.getcartesian(movement)
|
||||
if (cartesian || allowNull) {
|
||||
cb(movement, cartesian)
|
||||
}
|
||||
}, Cesium.ScreenSpaceEventType.RIGHT_DOWN)
|
||||
}
|
||||
|
||||
mouse_right_up(cb, allowNull = false) {
|
||||
this.handler && this.handler.setInputAction((movement) => {
|
||||
let cartesian = this.getcartesian(movement)
|
||||
if (cartesian || allowNull) {
|
||||
cb(movement, cartesian)
|
||||
}
|
||||
}, Cesium.ScreenSpaceEventType.RIGHT_UP)
|
||||
}
|
||||
|
||||
mouse_wheel(cb) {
|
||||
this.handler && this.handler.setInputAction(() => {
|
||||
cb()
|
||||
}, Cesium.ScreenSpaceEventType.WHEEL)
|
||||
}
|
||||
|
||||
getcartesian(movement) {
|
||||
// if (movement.endPosition) {
|
||||
// movement.endPosition.y -= 2
|
||||
// }
|
||||
let position = movement.position || movement.endPosition
|
||||
if(movement.position1 && movement.position2) {
|
||||
position = {
|
||||
x: (movement.position1.x + movement.position2.x) / 2,
|
||||
y: (movement.position1.y + movement.position2.y) / 2,
|
||||
}
|
||||
}
|
||||
let cartesian = this.viewer.scene.pickPosition(position)
|
||||
if (!cartesian) {
|
||||
const ray = this.viewer.camera.getPickRay(position); //相交的射线
|
||||
let pickedObjects = this.viewer.scene.drillPickFromRay(ray, 10);
|
||||
let result = {}
|
||||
for (let i = 0; i < pickedObjects.length; i++) {
|
||||
if (pickedObjects[i].position) {
|
||||
result = pickedObjects[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
cartesian = result.position
|
||||
if(!cartesian) {
|
||||
cartesian = this.viewer.scene.globe.pick(ray, this.viewer.scene);
|
||||
}
|
||||
}
|
||||
// console.log(cartesian)
|
||||
// const updatedPositions = await Cesium.sampleTerrainMostDetailed(this.sdk.viewer.terrainProvider, Cesium.Cartographic.fromCartesian(cartesian, this.viewer.scene.globe.ellipsoid));
|
||||
// console.log(updatedPositions)
|
||||
return cartesian
|
||||
// return this.earth.czm.viewer.scene.pickPosition(position)
|
||||
}
|
||||
|
||||
//鼠标右键+键盘ctrl
|
||||
mouse_right_keyboard_ctrl(cb) {
|
||||
// //左键点击事件
|
||||
this.handler && this.handler.setInputAction(
|
||||
(movement) => {
|
||||
let cartesian = this.getcartesian(movement)
|
||||
if (cartesian) {
|
||||
cb(movement, cartesian)
|
||||
}
|
||||
},
|
||||
Cesium.ScreenSpaceEventType.RIGHT_CLICK,
|
||||
Cesium.KeyboardEventModifier.CTRL
|
||||
)
|
||||
}
|
||||
|
||||
// 手势-双指触摸开始
|
||||
gesture_pinck_start(cb) {
|
||||
this.handler && this.handler.setInputAction((movement) => {
|
||||
let cartesian = this.getcartesian(movement)
|
||||
if (cartesian) {
|
||||
cb(movement, cartesian)
|
||||
}
|
||||
}, Cesium.ScreenSpaceEventType.PINCH_START)
|
||||
}
|
||||
|
||||
//手势-双指触摸开始+键盘ctrl
|
||||
gesture_pinck_start_keyboard_ctrl(cb) {
|
||||
this.handler && this.handler.setInputAction(
|
||||
(movement) => {
|
||||
let cartesian = this.getcartesian(movement)
|
||||
if (cartesian) {
|
||||
cb(movement, cartesian)
|
||||
}
|
||||
},
|
||||
Cesium.ScreenSpaceEventType.PINCH_START,
|
||||
Cesium.KeyboardEventModifier.CTRL
|
||||
)
|
||||
}
|
||||
|
||||
// 手势-双指触摸结束
|
||||
gesture_pinck_end(cb) {
|
||||
this.handler && this.handler.setInputAction((movement) => {
|
||||
cb()
|
||||
}, Cesium.ScreenSpaceEventType.PINCH_END)
|
||||
}
|
||||
|
||||
// 手势-双指触摸修改
|
||||
gesture_pinck_move(cb) {
|
||||
this.handler && this.handler.setInputAction((movement) => {
|
||||
// let cartesian = this.getcartesian(movement)
|
||||
// if (cartesian) {
|
||||
// cb(movement, cartesian)
|
||||
// }
|
||||
}, Cesium.ScreenSpaceEventType.PINCH_MOVE)
|
||||
}
|
||||
|
||||
destroy() {
|
||||
if (this.handler)
|
||||
this.handler.destroy() //关闭事件句柄
|
||||
this.handler = null
|
||||
}
|
||||
}
|
||||
578
src/Global/ClickCallback/index.js
Normal file
578
src/Global/ClickCallback/index.js
Normal file
@ -0,0 +1,578 @@
|
||||
/**
|
||||
* @name: click
|
||||
* @author: Administrator
|
||||
* @date: 2023-05-28 11:05
|
||||
* @description:click
|
||||
* @update: 2023-05-28 11:05
|
||||
*/
|
||||
let leftClickHandler = null
|
||||
let rightClickHandler = null
|
||||
let MoveHandler = null
|
||||
let leftClickCallbackMap = new Map()
|
||||
let rightClickCallbackMap = new Map()
|
||||
let MoveCallbackMap = new Map()
|
||||
let selectedFeature;
|
||||
|
||||
|
||||
function cartesian3Towgs84(cartesian, viewer) {
|
||||
var ellipsoid = viewer.scene.globe.ellipsoid
|
||||
var cartesian3 = new Cesium.Cartesian3(
|
||||
cartesian.x,
|
||||
cartesian.y,
|
||||
cartesian.z
|
||||
)
|
||||
var cartographic = ellipsoid.cartesianToCartographic(cartesian3)
|
||||
var lat = Cesium.Math.toDegrees(cartographic.latitude)
|
||||
var lng = Cesium.Math.toDegrees(cartographic.longitude)
|
||||
var alt = cartographic.height < 0 ? 0 : cartographic.height
|
||||
return {
|
||||
lng: lng,
|
||||
lat: lat,
|
||||
alt: alt,
|
||||
}
|
||||
}
|
||||
|
||||
function getcartesian(sdk, movement) {
|
||||
if (movement.endPosition) {
|
||||
movement.endPosition.y -= 2
|
||||
}
|
||||
let position = movement.position || movement.endPosition
|
||||
// 获取世界坐标系地表坐标,考虑地形,不包括模型,倾斜摄影模型表面;
|
||||
let cartesian = sdk.viewer.scene.pickPosition(position)
|
||||
if (!cartesian) {
|
||||
const ray = sdk.viewer.camera.getPickRay(position); //相交的射线
|
||||
cartesian = sdk.viewer.scene.globe.pick(ray, sdk.viewer.scene);
|
||||
}
|
||||
return cartesian
|
||||
}
|
||||
|
||||
function openLeftClick(sdk, cb) {
|
||||
if (!sdk || !sdk.viewer) {
|
||||
return
|
||||
}
|
||||
let click = true
|
||||
leftClickHandler = new Cesium.ScreenSpaceEventHandler(sdk.viewer.canvas)
|
||||
leftClickHandler.setInputAction((movement) => {
|
||||
let cartesian = sdk.viewer.scene.pickPosition(movement.position)
|
||||
if (!cartesian) {
|
||||
const ray = sdk.viewer.camera.getPickRay(movement.position); //相交的射线
|
||||
cartesian = sdk.viewer.scene.globe.pick(ray, sdk.viewer.scene);
|
||||
}
|
||||
if (!cartesian) {
|
||||
return
|
||||
}
|
||||
|
||||
let pos84 = cartesian3Towgs84(cartesian, sdk.viewer)
|
||||
|
||||
cb && cb(pos84)
|
||||
|
||||
if (click) {
|
||||
click = false
|
||||
setTimeout(() => {
|
||||
click = true
|
||||
}, 600);
|
||||
if (!YJ.Measure.GetMeasureStatus() && cartesian) {
|
||||
let flag = false
|
||||
for (let i = leftClickCallbackMap.size - 1; i >= 0; i--) {
|
||||
let key = Array.from(leftClickCallbackMap.keys())[i]
|
||||
let obj = leftClickCallbackMap.get(key)
|
||||
if (obj) {
|
||||
|
||||
if (obj.that) {
|
||||
// 是否为多边形
|
||||
if (obj.that.type === 'PolygonObject') {
|
||||
// 是否可点击y
|
||||
if (obj.that.picking) {
|
||||
if (obj.that.options.positions && obj.that.options.positions.length >= 3) {
|
||||
let pt = turf.point([pos84.lng, pos84.lat]);
|
||||
let polyPos = []
|
||||
for (let i = 0; i < obj.that.options.positions.length; i++) {
|
||||
polyPos.push([
|
||||
obj.that.options.positions[i].lng,
|
||||
obj.that.options.positions[i].lat
|
||||
])
|
||||
}
|
||||
polyPos.push([
|
||||
obj.that.options.positions[0].lng,
|
||||
obj.that.options.positions[0].lat
|
||||
])
|
||||
let poly = turf.polygon([polyPos]);
|
||||
let contain = turf.booleanPointInPolygon(pt, poly);
|
||||
if (contain) {
|
||||
obj.callback(
|
||||
movement,
|
||||
obj.that.options.id,
|
||||
cartesian3Towgs84(getcartesian(sdk, movement), sdk.viewer), obj.that)
|
||||
flag = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 聚集地
|
||||
else if (obj.that.type === 'AssembleObject') {
|
||||
if (obj.that.picking) {
|
||||
if (obj.that.options.positions && obj.that.options.positions.length >= 3) {
|
||||
let positions = obj.that.computeAssemble(obj.that.options.positions, true)
|
||||
let pt = turf.point([pos84.lng, pos84.lat]);
|
||||
let polyPos = []
|
||||
for (let i = 0; i < positions.length; i += 2) {
|
||||
polyPos.push([
|
||||
positions[i],
|
||||
positions[i + 1]
|
||||
])
|
||||
}
|
||||
let poly = turf.polygon([polyPos]);
|
||||
let contain = turf.booleanPointInPolygon(pt, poly);
|
||||
if (contain) {
|
||||
obj.callback(
|
||||
movement,
|
||||
obj.that.options.id,
|
||||
cartesian3Towgs84(getcartesian(sdk, movement), sdk.viewer), obj.that)
|
||||
flag = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 单箭头
|
||||
else if (obj.that.type === 'AttackArrowObject') {
|
||||
if (obj.that.picking) {
|
||||
if (obj.that.options.positions && obj.that.options.positions.length >= 3) {
|
||||
let pt = turf.point([pos84.lng, pos84.lat]);
|
||||
let positions = obj.that.computeAttackArrow(obj.that.options.positions)
|
||||
let polyPos = []
|
||||
for (let m = 0; m < positions.length; m++) {
|
||||
let pos84 = cartesian3Towgs84(positions[m], sdk.viewer)
|
||||
polyPos.push([pos84.lng, pos84.lat])
|
||||
}
|
||||
let poly = turf.polygon([polyPos]);
|
||||
let contain = turf.booleanPointInPolygon(pt, poly);
|
||||
if (contain) {
|
||||
obj.callback(
|
||||
movement,
|
||||
obj.that.options.id,
|
||||
cartesian3Towgs84(getcartesian(sdk, movement), sdk.viewer), obj.that)
|
||||
flag = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 双箭头
|
||||
else if (obj.that.type === 'PincerArrowObject') {
|
||||
if (obj.that.picking) {
|
||||
if (obj.that.options.positions && obj.that.options.positions.length >= 5) {
|
||||
let pt = turf.point([pos84.lng, pos84.lat]);
|
||||
let positions = obj.that.computePincerArrow(obj.that.options.positions)
|
||||
let polyPos = []
|
||||
for (let m = 0; m < positions.length; m++) {
|
||||
let pos84 = cartesian3Towgs84(positions[m], sdk.viewer)
|
||||
polyPos.push([pos84.lng, pos84.lat])
|
||||
}
|
||||
let pos84_0 = cartesian3Towgs84(positions[0], sdk.viewer)
|
||||
polyPos.push([pos84_0.lng, pos84_0.lat])
|
||||
let poly = turf.polygon([polyPos]);
|
||||
let contain = turf.booleanPointInPolygon(pt, poly);
|
||||
if (contain) {
|
||||
obj.callback(
|
||||
movement,
|
||||
obj.that.options.id,
|
||||
cartesian3Towgs84(getcartesian(sdk, movement), sdk.viewer), obj.that)
|
||||
flag = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 圆
|
||||
else if (obj.that.type === 'CircleObject') {
|
||||
if (obj.that.picking) {
|
||||
let pt = turf.point([pos84.lng, pos84.lat]);
|
||||
if (obj.that.options.center && obj.that.options.radius) {
|
||||
let center = [obj.that.options.center.lng, obj.that.options.center.lat];
|
||||
let radius = obj.that.options.radius / 1000;
|
||||
let options = { steps: 360, units: 'kilometers' };
|
||||
let circle = turf.circle(center, radius, options);
|
||||
let contain = turf.booleanPointInPolygon(pt, circle);
|
||||
if (contain) {
|
||||
obj.callback(
|
||||
movement,
|
||||
obj.that.options.id,
|
||||
cartesian3Towgs84(getcartesian(sdk, movement), sdk.viewer), obj.that)
|
||||
flag = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
// 扇形
|
||||
else if (obj.that.type === 'SectorObject') {
|
||||
if (obj.that.picking) {
|
||||
let pt = turf.point([pos84.lng, pos84.lat]);
|
||||
if (obj.that.options.center && obj.that.options.radius && obj.that.options.startAngle && obj.that.options.endAngle) {
|
||||
let positions = obj.that.calSector(obj.that.options.center, obj.that.options.radius, obj.that.options.startAngle, obj.that.options.endAngle, undefined, true)
|
||||
let polyPos = []
|
||||
for (let m = 0; m < positions.length; m++) {
|
||||
polyPos.push([positions[m].lng, positions[m].lat])
|
||||
}
|
||||
let poly = turf.polygon([polyPos]);
|
||||
let contain = turf.booleanPointInPolygon(pt, poly);
|
||||
if (contain) {
|
||||
obj.callback(
|
||||
movement,
|
||||
obj.that.options.id,
|
||||
cartesian3Towgs84(getcartesian(sdk, movement), sdk.viewer), obj.that)
|
||||
flag = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!flag) {
|
||||
const pick = sdk.viewer.scene.pick(movement.position)
|
||||
if (pick) {
|
||||
if (pick.id) {
|
||||
let entityId
|
||||
// 矢量
|
||||
if (pick.id.type && pick.id.type === 'vector' && pick.id.parentId) {
|
||||
let obj = leftClickCallbackMap.get(pick.id.parentId)
|
||||
if (obj.that.picking && obj.that.geojson) {
|
||||
for (let i = 0; i < obj.that.geojson.features.length; i++) {
|
||||
if (obj.that.geojson.features[i].id === pick.id._id) {
|
||||
obj.callback(
|
||||
movement,
|
||||
obj.that.geojson.features[i].id,
|
||||
cartesian3Towgs84(getcartesian(sdk, movement), sdk.viewer), obj.that)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (typeof pick.id.id == 'string') {
|
||||
let array = pick.id.id.split('-')
|
||||
array.splice(array.length - 1, 1)
|
||||
entityId = array.join('-')
|
||||
}
|
||||
|
||||
if (pick.id.properties && pick.id.properties.id && leftClickCallbackMap.has(pick.id.properties.id._value)) {
|
||||
let obj = leftClickCallbackMap.get(pick.id.properties.id._value)
|
||||
if (obj.that.picking) {
|
||||
obj.callback(
|
||||
movement,
|
||||
pick.id.properties.id._value,
|
||||
cartesian3Towgs84(getcartesian(sdk, movement), sdk.viewer), obj.that)
|
||||
}
|
||||
}
|
||||
else if (leftClickCallbackMap.has(pick.id.id)) {
|
||||
let obj = leftClickCallbackMap.get(pick.id.id)
|
||||
if (obj.that.picking) {
|
||||
obj.callback(
|
||||
movement,
|
||||
pick.id.id,
|
||||
cartesian3Towgs84(getcartesian(sdk, movement), sdk.viewer), obj.that)
|
||||
}
|
||||
}
|
||||
else if (entityId && leftClickCallbackMap.has(entityId)) {
|
||||
let obj = leftClickCallbackMap.get(entityId)
|
||||
if (obj.that.picking) {
|
||||
obj.callback(
|
||||
movement,
|
||||
entityId,
|
||||
cartesian3Towgs84(getcartesian(sdk, movement), sdk.viewer), obj.that)
|
||||
}
|
||||
}
|
||||
else if (pick.primitive) {
|
||||
if (typeof pick.id == 'string' && leftClickCallbackMap.has(pick.id)) {
|
||||
let obj = leftClickCallbackMap.get(pick.id)
|
||||
obj.callback(
|
||||
movement,
|
||||
pick.id,
|
||||
cartesian3Towgs84(getcartesian(sdk, movement), sdk.viewer), obj.that)
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (pick.primitive && pick.primitive.id) {
|
||||
if (leftClickCallbackMap.has(pick.primitive.id)) {
|
||||
let obj = leftClickCallbackMap.get(pick.primitive.id)
|
||||
if (obj.that.picking) {
|
||||
if (obj.that.type === 'bim') {
|
||||
if (YJ.Global.getBimPickStatus(sdk)) {
|
||||
obj.callback(
|
||||
movement,
|
||||
pick.primitive,
|
||||
cartesian3Towgs84(getcartesian(sdk, movement), sdk.viewer), obj.that)
|
||||
}
|
||||
}
|
||||
else {
|
||||
obj.callback(
|
||||
movement,
|
||||
pick.primitive.id,
|
||||
cartesian3Towgs84(getcartesian(sdk, movement), sdk.viewer), obj.that)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pick.content && (!pick.primitive || !pick.primitive.id)) {
|
||||
if (leftClickCallbackMap.has(pick.content.tileset.id)) {
|
||||
let obj = leftClickCallbackMap.get(pick.content.tileset.id)
|
||||
if (obj.that.picking) {
|
||||
if (obj.that.type === 'bim') {
|
||||
if (YJ.Global.getBimPickStatus(sdk)) {
|
||||
obj.callback(
|
||||
movement,
|
||||
pick.content.tileset,
|
||||
cartesian3Towgs84(getcartesian(sdk, movement), sdk.viewer), obj.that)
|
||||
}
|
||||
}
|
||||
else {
|
||||
obj.callback(
|
||||
movement,
|
||||
pick.content.tileset.id,
|
||||
cartesian3Towgs84(getcartesian(sdk, movement), sdk.viewer), obj.that)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// if (click) {
|
||||
// click = false
|
||||
// setTimeout(() => {
|
||||
// click = true
|
||||
// }, 300);
|
||||
// if (!YJ.Measure.GetMeasureStatus()) {
|
||||
|
||||
// }
|
||||
// }
|
||||
}, Cesium.ScreenSpaceEventType.LEFT_CLICK)
|
||||
|
||||
// leftClickHandler.setInputAction(function (movement) {
|
||||
// const feature = sdk.viewer.scene.pick(movement.endPosition);
|
||||
// // unselectFeature(selectedFeature);
|
||||
// if (selectedFeature) {
|
||||
// selectedFeature.color = Cesium.Color.WHITE;
|
||||
// }
|
||||
// selectedFeature = feature
|
||||
// if (feature) {
|
||||
// feature.color = Cesium.Color.YELLOW;
|
||||
// }
|
||||
// }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
function closeLeftClick(sdk) {
|
||||
leftClickHandler.destroy() //关闭事件句柄
|
||||
leftClickHandler = null
|
||||
// }
|
||||
}
|
||||
|
||||
function openRightClick(sdk) {
|
||||
if (!sdk || !sdk.viewer) {
|
||||
return
|
||||
}
|
||||
rightClickHandler = new Cesium.ScreenSpaceEventHandler(sdk.viewer.canvas)
|
||||
rightClickHandler.setInputAction((movement) => {
|
||||
if (!YJ.Measure.GetMeasureStatus()) {
|
||||
const pick = sdk.viewer.scene.pick(movement.position)
|
||||
if (pick && pick.id) {
|
||||
let id
|
||||
if (pick.id.type && pick.id.type === 'vector' && pick.id.parentId) {
|
||||
let obj = rightClickCallbackMap.get(pick.id.parentId)
|
||||
if (obj.that.picking && obj.that.geojson) {
|
||||
for (let i = 0; i < obj.that.geojson.features.length; i++) {
|
||||
if (obj.that.geojson.features[i].id === pick.id._id) {
|
||||
obj.callback(
|
||||
movement,
|
||||
obj.that.geojson.features[i].id,
|
||||
cartesian3Towgs84(getcartesian(sdk, movement), sdk.viewer), obj.that)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (typeof pick.id === 'string') {
|
||||
id = pick.id
|
||||
}
|
||||
else {
|
||||
id = pick.id.id
|
||||
}
|
||||
if (rightClickCallbackMap.has(id)) {
|
||||
let obj = rightClickCallbackMap.get(id)
|
||||
if (obj.that.picking) {
|
||||
let cartesian = getcartesian(sdk, movement)
|
||||
if (!cartesian) {
|
||||
return
|
||||
}
|
||||
obj.callback(
|
||||
movement,
|
||||
id,
|
||||
cartesian3Towgs84(cartesian, sdk.viewer), obj.that)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pick && pick.content) {
|
||||
if (rightClickCallbackMap.has(pick.content.tileset.id)) {
|
||||
let obj = rightClickCallbackMap.get(pick.content.tileset.id)
|
||||
if (obj.that.picking) {
|
||||
if (obj.that.type === 'bim') {
|
||||
if (YJ.Global.getBimPickStatus(sdk)) {
|
||||
let cartesian = getcartesian(sdk, movement)
|
||||
if (!cartesian) {
|
||||
return
|
||||
}
|
||||
obj.callback(
|
||||
movement,
|
||||
pick.getProperty('id'),
|
||||
cartesian3Towgs84(cartesian, sdk.viewer), obj.that)
|
||||
}
|
||||
}
|
||||
else {
|
||||
let cartesian = getcartesian(sdk, movement)
|
||||
if (!cartesian) {
|
||||
return
|
||||
}
|
||||
obj.callback(
|
||||
movement,
|
||||
pick.content.tileset.id,
|
||||
cartesian3Towgs84(cartesian, sdk.viewer), obj.that)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK)
|
||||
}
|
||||
|
||||
function closeRightClick() {
|
||||
if (rightClickHandler) {
|
||||
rightClickHandler.destroy() //关闭事件句柄
|
||||
rightClickHandler = null
|
||||
}
|
||||
}
|
||||
|
||||
function openMove(sdk) {
|
||||
MoveHandler = new Cesium.ScreenSpaceEventHandler(sdk.viewer.canvas)
|
||||
MoveHandler.setInputAction(function (movement) {
|
||||
const pick = sdk.viewer.scene.pick(movement.endPosition);
|
||||
// unselectFeature(selectedFeature);
|
||||
// if (selectedFeature) {
|
||||
// let color = '#fff'
|
||||
// let state = selectedFeature.getProperty('state')
|
||||
// switch (state) {
|
||||
// case '0':
|
||||
// color = '#fff'
|
||||
// break;
|
||||
// case '1':
|
||||
// color = '#f00'
|
||||
// break;
|
||||
// case '2':
|
||||
// color = '#0f0'
|
||||
// break;
|
||||
// case '3':
|
||||
// color = '#00f'
|
||||
// break;
|
||||
// default:
|
||||
// }
|
||||
// selectedFeature.color = Cesium.Color.fromCssColorString(color).withAlpha(selectedFeature.tileset.transparency)
|
||||
// }
|
||||
// if (pick && pick.id) { }
|
||||
// if (pick && pick.content) {
|
||||
// if (MoveCallbackMap.has(pick.content.tileset.id)) {
|
||||
// let obj = MoveCallbackMap.get(pick.content.tileset.id)
|
||||
// if (obj.that.picking) {
|
||||
// if (obj.that.type === 'bim') {
|
||||
// if (YJ.Global.getBimPickStatus(sdk)) {
|
||||
// selectedFeature = pick
|
||||
// pick.color = Cesium.Color.YELLOW;
|
||||
// }
|
||||
// else {
|
||||
// selectedFeature = null
|
||||
// }
|
||||
// }
|
||||
// else {
|
||||
// selectedFeature = pick
|
||||
// pick.color = Cesium.Color.YELLOW;
|
||||
// }
|
||||
// }
|
||||
// else {
|
||||
// selectedFeature = null
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
|
||||
}
|
||||
|
||||
function closeMove() {
|
||||
if (MoveHandler) {
|
||||
MoveHandler.destroy() //关闭事件句柄
|
||||
MoveHandler = null
|
||||
}
|
||||
}
|
||||
|
||||
/*注册左键回调*/
|
||||
function regLeftClickCallback(id, callback, that) {
|
||||
|
||||
leftClickCallbackMap.set(id, { callback, that })
|
||||
}/*取消左键回调*/
|
||||
function unRegLeftClickCallback(id,) {
|
||||
leftClickCallbackMap.delete(id,)
|
||||
}
|
||||
|
||||
/*注册右键回调*/
|
||||
function regRightClickCallback(id, callback, that) {
|
||||
rightClickCallbackMap.set(id, { callback, that })
|
||||
}/*取消右键回调*/
|
||||
function unRegRightClickCallback(id,) {
|
||||
rightClickCallbackMap.delete(id,)
|
||||
}
|
||||
|
||||
/*注册左键回调*/
|
||||
function regMoveCallback(id, callback, that) {
|
||||
MoveCallbackMap.set(id, { callback, that })
|
||||
}/*取消左键回调*/
|
||||
function unregMoveCallback(id,) {
|
||||
MoveCallbackMap.delete(id,)
|
||||
}
|
||||
|
||||
function getLeftClickState() {
|
||||
if (leftClickHandler) {
|
||||
return true
|
||||
}
|
||||
else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
function getRightClickState() {
|
||||
if (rightClickHandler) {
|
||||
return true
|
||||
}
|
||||
else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
function getMoveState() {
|
||||
if (MoveHandler) {
|
||||
return true
|
||||
}
|
||||
else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export { openLeftClick, closeLeftClick, regLeftClickCallback, unRegLeftClickCallback, openRightClick, closeRightClick, regRightClickCallback, unRegRightClickCallback, openMove, closeMove, regMoveCallback, unregMoveCallback, getLeftClickState, getRightClickState, getMoveState }
|
||||
253
src/Global/Contour/index.js
Normal file
253
src/Global/Contour/index.js
Normal file
@ -0,0 +1,253 @@
|
||||
/**
|
||||
* 等高线
|
||||
*/
|
||||
import Dialog from "../../Obj/Element/Dialog";
|
||||
import Tools from "../../Tools";
|
||||
|
||||
let _DialogObject = null;
|
||||
let material = null;
|
||||
let handler = null;
|
||||
let activeHeightElm = null;
|
||||
let tools
|
||||
activeHeightElm = document.createElement('div')
|
||||
activeHeightElm.className = 'YJ-customize-active-height-elm'
|
||||
activeHeightElm.style.position = 'absolute'
|
||||
activeHeightElm.style.left = '10px'
|
||||
activeHeightElm.style.top = '10px'
|
||||
activeHeightElm.style.width = '100px'
|
||||
// activeHeightElm.style.backgroundColor = 'rgba(0, 0, 0, 0.5)'
|
||||
activeHeightElm.style.textAlign = 'center'
|
||||
activeHeightElm.style.pointerEvents = 'none'
|
||||
activeHeightElm.style.color = '#ff0000'
|
||||
activeHeightElm.style.display = 'none'
|
||||
async function dialog(sdk) {
|
||||
if (!sdk || _DialogObject) {
|
||||
return
|
||||
}
|
||||
if (!material) {
|
||||
createMaterial()
|
||||
}
|
||||
if (!tools) {
|
||||
tools = new Tools()
|
||||
}
|
||||
|
||||
_DialogObject = await new Dialog(sdk, {}, {
|
||||
title: "等高线", left: '180px',
|
||||
top: '100px',
|
||||
confirmCallBack: options => { },
|
||||
closeCallBack: () => {
|
||||
_DialogObject = null
|
||||
}
|
||||
});
|
||||
|
||||
_DialogObject._element.body.className =
|
||||
_DialogObject._element.body.className + ' contour'
|
||||
let contentElm = document.createElement('div')
|
||||
contentElm.innerHTML = `
|
||||
<span class="custom-divider"></span>
|
||||
<div class="div-item">
|
||||
<div class="row">
|
||||
<div class="col input-select-unit-box">
|
||||
<span class="label">高差</span>
|
||||
<div class="input-number input-number-unit-1">
|
||||
<input class="input gap" type="number" title="" min="0" max="1000">
|
||||
<span class="unit">m</span>
|
||||
<span class="arrow"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col input-select-unit-box" style="flex: 0 0 120px;">
|
||||
<span class="label">主线颜色</span>
|
||||
<div class="primary-lice-color"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col input-select-unit-box">
|
||||
<span class="label">次线条数</span>
|
||||
<div class="input-number input-number-unit-1">
|
||||
<input class="input gap2" type="number" title="" min="0" max="10">
|
||||
<span class="unit"></span>
|
||||
<span class="arrow"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col input-select-unit-box" style="flex: 0 0 120px;">
|
||||
<span class="label">次线颜色</span>
|
||||
<div class="secondary-lice-color"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" style="align-items: flex-start;">
|
||||
<div class="col">
|
||||
</div>
|
||||
<div class="col" style="flex: 0 0 120px;">
|
||||
<span class="label">开关</span>
|
||||
<input class="btn-switch" type="checkbox">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="custom-divider"></span>
|
||||
`
|
||||
contentElm.innerHTML = `
|
||||
<span class="custom-divider"></span>
|
||||
<div class="div-item">
|
||||
<div class="row" style="align-items: flex-start;">
|
||||
<div class="col" style="flex: 0 0 120px;">
|
||||
<span class="label">开关</span>
|
||||
<input class="btn-switch" type="checkbox">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
_DialogObject.contentAppChild(contentElm)
|
||||
|
||||
contentElm.getElementsByClassName('btn-switch')[0].addEventListener('change', (e) => {
|
||||
if (e.target.checked) {
|
||||
if (handler) {
|
||||
handler.destroy()
|
||||
}
|
||||
if (!sdk.viewer.container.getElementsByClassName('YJ-customize-active-height-elm')[0]) {
|
||||
sdk.viewer.container.appendChild(activeHeightElm)
|
||||
}
|
||||
|
||||
handler = new Cesium.ScreenSpaceEventHandler(
|
||||
sdk.viewer.canvas
|
||||
)
|
||||
handler.setInputAction((movement) => {
|
||||
let cartesian = sdk.viewer.scene.pickPosition(movement.endPosition)
|
||||
if (cartesian) {
|
||||
let top = 0
|
||||
let left = 0
|
||||
if (sdk.viewer && sdk.viewer._element) {
|
||||
let element = sdk.viewer._element.getElementsByClassName('cesium-widget')[0].getElementsByTagName('canvas')[0]
|
||||
top = element.getBoundingClientRect().top + window.scrollY
|
||||
left = element.getBoundingClientRect().left + window.scrollX
|
||||
}
|
||||
activeHeightElm.style.left = movement.endPosition.x - 50 + left + 'px'
|
||||
activeHeightElm.style.top = movement.endPosition.y - 40 + top + 'px'
|
||||
activeHeightElm.style.display = 'block'
|
||||
let pos84 = tools.cartesian3Towgs84(cartesian, sdk.viewer)
|
||||
let mainContourHeight = Math.floor(pos84.alt / material.uniforms.spacing) * material.uniforms.spacing
|
||||
let gap = pos84.alt - mainContourHeight
|
||||
let gap2 = material.uniforms.spacing / (material.uniforms.secondaryLinesCount + 1)
|
||||
let activeHeight = Math.floor(gap / gap2) * gap2 + mainContourHeight
|
||||
if ((pos84.alt - activeHeight) > gap2 / 2) {
|
||||
activeHeight = activeHeight + gap2
|
||||
}
|
||||
material.uniforms.mouseHeight = pos84.alt
|
||||
material.uniforms.mousePosition = cartesian
|
||||
activeHeightElm.innerHTML = `${activeHeight.toFixed(0)}`
|
||||
}
|
||||
else {
|
||||
activeHeightElm.style.display = 'none'
|
||||
}
|
||||
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
|
||||
sdk.viewer.scene.globe.material = material;
|
||||
} else {
|
||||
if (handler) {
|
||||
handler.destroy()
|
||||
handler = null
|
||||
}
|
||||
if (sdk.viewer.container.getElementsByClassName('YJ-customize-active-height-elm')[0]) {
|
||||
activeHeightElm.style.display = 'none'
|
||||
sdk.viewer.container.removeChild(activeHeightElm)
|
||||
}
|
||||
sdk.viewer.scene.globe.material = null;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function createMaterial() {
|
||||
Cesium.Material._materialCache._materials.ElevationContour.fabric.source = `
|
||||
uniform vec4 color;
|
||||
uniform vec4 secondaryLinesColor;
|
||||
uniform float spacing;
|
||||
uniform float width;
|
||||
uniform float secondaryLinesWidth;
|
||||
uniform float mouseHeight;
|
||||
uniform float secondaryLinesCount; // 0=无次线, 1=1条次线, 2=2条次线...
|
||||
|
||||
czm_material czm_getMaterial(czm_materialInput materialInput)
|
||||
{
|
||||
czm_material material = czm_getDefaultMaterial(materialInput);
|
||||
|
||||
// 主等高线计算
|
||||
float distanceToMainContour = mod(materialInput.height, spacing);
|
||||
|
||||
// 抗锯齿计算
|
||||
#if (__VERSION__ == 300 || defined(GL_OES_standard_derivatives))
|
||||
float dxc = abs(dFdx(materialInput.height));
|
||||
float dyc = abs(dFdy(materialInput.height));
|
||||
float dFMain = max(dxc, dyc) * czm_pixelRatio * width;
|
||||
#else
|
||||
float dFMain = czm_pixelRatio * width;
|
||||
#endif
|
||||
|
||||
bool isMainContour = distanceToMainContour < dFMain;
|
||||
bool isSecondaryContour = false;
|
||||
float dFSecondary = 0.0;
|
||||
float secondarySpacing = 0.0;
|
||||
|
||||
// 只有当存在次线时才计算次线
|
||||
if(secondaryLinesCount > 0.0) {
|
||||
secondarySpacing = spacing / (secondaryLinesCount + 1.0);
|
||||
float distanceToSecondaryContour = mod(materialInput.height, secondarySpacing);
|
||||
|
||||
// 确保次线不会与主线重叠
|
||||
float minDistanceToMain = min(distanceToMainContour, spacing - distanceToMainContour);
|
||||
bool notCloseToMain = minDistanceToMain > dFMain * 2.0; // 2倍线宽缓冲
|
||||
|
||||
#if (__VERSION__ == 300 || defined(GL_OES_standard_derivatives))
|
||||
dFSecondary = max(dxc, dyc) * czm_pixelRatio * secondaryLinesWidth;
|
||||
#else
|
||||
dFSecondary = czm_pixelRatio * secondaryLinesWidth;
|
||||
#endif
|
||||
|
||||
isSecondaryContour = (distanceToSecondaryContour < dFSecondary) && notCloseToMain;
|
||||
}
|
||||
|
||||
// 计算当前高度所属的等高线高度
|
||||
float mainContourHeight = floor(materialInput.height / spacing) * spacing;
|
||||
float secondaryContourHeight = floor(materialInput.height / spacing * (secondaryLinesCount + 1.0)) * spacing / (secondaryLinesCount + 1.0);
|
||||
|
||||
// 高亮判断
|
||||
bool shouldHighlight = false;
|
||||
if(isMainContour && abs(mainContourHeight - mouseHeight) < 0.5 * (spacing/(secondaryLinesCount+1.0))) {
|
||||
shouldHighlight = true;
|
||||
} else if(isSecondaryContour && abs(secondaryContourHeight - mouseHeight) < 0.5 * (spacing/(secondaryLinesCount+1.0))) {
|
||||
shouldHighlight = true;
|
||||
}
|
||||
|
||||
// 颜色输出
|
||||
vec4 outColor;
|
||||
if(shouldHighlight) {
|
||||
outColor = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
} else if(isMainContour) {
|
||||
outColor = czm_gammaCorrect(vec4(color.rgb, color.a));
|
||||
} else if(isSecondaryContour) {
|
||||
outColor = czm_gammaCorrect(vec4(secondaryLinesColor.rgb, secondaryLinesColor.a));
|
||||
} else {
|
||||
outColor = vec4(0.0);
|
||||
}
|
||||
|
||||
material.diffuse = outColor.rgb;
|
||||
material.alpha = outColor.a;
|
||||
return material;
|
||||
}
|
||||
`
|
||||
|
||||
material = new Cesium.Material({
|
||||
fabric: {
|
||||
type: "ElevationContour",
|
||||
uniforms: {
|
||||
width: 2,
|
||||
secondaryLinesWidth: 1, // 次级线宽度
|
||||
spacing: 200,
|
||||
color: Cesium.Color.fromCssColorString('#ffd000'),
|
||||
secondaryLinesColor: Cesium.Color.fromCssColorString('#0dff00').withAlpha(0.5),
|
||||
mouseHeight: -100000,
|
||||
mousePosition: new Cesium.Cartesian3(0, 0, 0),
|
||||
secondaryLinesCount: 3
|
||||
},
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export { dialog }
|
||||
37
src/Global/DTH/changeClassificationPrimitive.js
Normal file
37
src/Global/DTH/changeClassificationPrimitive.js
Normal file
@ -0,0 +1,37 @@
|
||||
function changeClassificationPrimitive(options, array) {
|
||||
this.options = options
|
||||
this.array = array
|
||||
}
|
||||
|
||||
changeClassificationPrimitive.prototype.getGeometry = function () {
|
||||
return Cesium.PolygonGeometry.createGeometry(this.options);
|
||||
};
|
||||
changeClassificationPrimitive.prototype.update = function (context, frameState, commandList) {
|
||||
var geometry = this.getGeometry();
|
||||
if (!geometry) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._primitive = new Cesium.ClassificationPrimitive({
|
||||
geometryInstances: new Cesium.GeometryInstance({
|
||||
geometry: geometry,
|
||||
id: {
|
||||
type: 'dth',
|
||||
...this.array,
|
||||
},
|
||||
attributes: {
|
||||
color: Cesium.ColorGeometryInstanceAttribute.fromColor(
|
||||
Cesium.Color.fromRandom({ alpha: 0.5 })
|
||||
),
|
||||
show: new Cesium.ShowGeometryInstanceAttribute(true),
|
||||
}
|
||||
}),
|
||||
classificationType: Cesium.ClassificationType.CESIUM_3D_TILE,
|
||||
});
|
||||
var primitive = this._primitive
|
||||
|
||||
primitive.update(context, frameState, commandList);
|
||||
|
||||
};
|
||||
|
||||
export { changeClassificationPrimitive }
|
||||
538
src/Global/DTH/index.js
Normal file
538
src/Global/DTH/index.js
Normal file
@ -0,0 +1,538 @@
|
||||
import { getHost, getToken } from "../../on";
|
||||
class DTH {
|
||||
constructor(sdk, options = {}) {
|
||||
this.sdk = sdk
|
||||
this.primitives = {
|
||||
building: [],
|
||||
unit: [],
|
||||
dth: []
|
||||
}
|
||||
this.options = { ...options }
|
||||
this.options.host = this.options.host || getHost()
|
||||
this.temporaryDth = []
|
||||
this.dth = {}
|
||||
this.PickBuildingEvent = new Cesium.Event();
|
||||
this.initEvents()
|
||||
this.activeBuilding
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 注册点击的事件回调
|
||||
* @memberOf DTH
|
||||
* */
|
||||
PickCallback(that, cb) {
|
||||
this.PickBuildingEvent.addEventListener(
|
||||
cb,
|
||||
that
|
||||
)
|
||||
}
|
||||
|
||||
//场景事件
|
||||
initEvents() {
|
||||
new Cesium.ScreenSpaceEventHandler(this.sdk.viewer.scene.canvas).setInputAction(((e) => {
|
||||
if (YJ.Measure.GetMeasureStatus()) {
|
||||
return
|
||||
}
|
||||
if (!this.isActivate) return;
|
||||
let pickFeature = this.sdk.viewer.scene.pick(e.position);
|
||||
if (pickFeature) {
|
||||
//点击了已有的分户单体化
|
||||
if (pickFeature.primitive && pickFeature.primitive instanceof Cesium.ClassificationPrimitive && pickFeature.id && (pickFeature.id.type == "yj-dth-dth" || pickFeature.id.type == "yj-dth-highlight")) {
|
||||
this.getIDBypickFeature(pickFeature); //处理点击到的楼层
|
||||
return;
|
||||
}
|
||||
if (pickFeature.primitive && pickFeature.primitive instanceof Cesium.ClassificationPrimitive && pickFeature.id && pickFeature.id.type == "yj-dth-unit") {
|
||||
this.highlightPrimitive && this.sdk.viewer.scene.primitives.remove(this.highlightPrimitive)
|
||||
this.handlePickEvent(pickFeature.id)
|
||||
return;
|
||||
}
|
||||
|
||||
// if (pickFeature.id && pickFeature.id.type === 'yj-dth-highlight') {
|
||||
// return;
|
||||
// }
|
||||
}
|
||||
|
||||
this.highlightPrimitive && this.sdk.viewer.scene.primitives.remove(this.highlightPrimitive)
|
||||
let position = this.sdk.viewer.scene.pickPosition(e.position); //屏幕坐标转为笛卡尔空间坐标
|
||||
if (!position) return;
|
||||
|
||||
let c = Cesium.Cartographic.fromCartesian(position); //笛卡尔坐标转为经纬度(弧度)
|
||||
let point = [Cesium.Math.toDegrees(c.longitude), Cesium.Math.toDegrees(c.latitude)]; //转为经纬度点
|
||||
this.queryByPoint(point, c.height);
|
||||
}), Cesium.ScreenSpaceEventType.LEFT_CLICK);
|
||||
|
||||
let coverLabelEntity = this.sdk.viewer.entities.getOrCreateEntity('yj-dth-cover-label')
|
||||
coverLabelEntity.show = false
|
||||
// this.sdk.viewer.entities.add({
|
||||
// position: Cesium.Cartesian3.fromDegrees(-75.1641667, 39.9522222),
|
||||
// label: {
|
||||
// text: "Philadelphia",
|
||||
// font: "24px Helvetica",
|
||||
// fillColor: Cesium.Color.SKYBLUE,
|
||||
// outlineColor: Cesium.Color.BLACK,
|
||||
// outlineWidth: 2,
|
||||
// style: Cesium.LabelStyle.FILL_AND_OUTLINE,
|
||||
// },
|
||||
// });
|
||||
let lastPickTime = 0;
|
||||
let _this = this
|
||||
let timeoutEvent
|
||||
new Cesium.ScreenSpaceEventHandler(this.sdk.viewer.scene.canvas).setInputAction(((movement) => {
|
||||
if (YJ.Measure.GetMeasureStatus()) {
|
||||
return
|
||||
}
|
||||
try {
|
||||
const now = Date.now();
|
||||
if (now - lastPickTime < 100) {
|
||||
clearTimeout(timeoutEvent)
|
||||
timeoutEvent = setTimeout(() => {
|
||||
pick(movement)
|
||||
}, 100);
|
||||
return
|
||||
}
|
||||
clearTimeout(timeoutEvent)
|
||||
lastPickTime = now;
|
||||
pick(movement)
|
||||
} catch (error) {
|
||||
}
|
||||
}), Cesium.ScreenSpaceEventType.MOUSE_MOVE);
|
||||
function pick(e) {
|
||||
let pickFeature = _this.sdk.viewer.scene.pick(e.endPosition);
|
||||
if (pickFeature) {
|
||||
let labelText = ''
|
||||
if (pickFeature.primitive && pickFeature.primitive instanceof Cesium.ClassificationPrimitive && pickFeature.id && (pickFeature.id.type === "yj-dth-dth" || pickFeature.id.type === "yj-dth-highlight")) {
|
||||
labelText = pickFeature.id.build_info.name + ' - ' + pickFeature.id.unit_info.name + ' - ' + pickFeature.id.room_num
|
||||
}
|
||||
else if (pickFeature.primitive && pickFeature.primitive instanceof Cesium.ClassificationPrimitive && pickFeature.id && pickFeature.id.type === "yj-dth-unit") {
|
||||
if (pickFeature.id.build_info.name) {
|
||||
labelText = pickFeature.id.build_info.name + ' - ' + pickFeature.id.name
|
||||
}
|
||||
}
|
||||
else if (pickFeature.primitive && pickFeature.primitive instanceof Cesium.ClassificationPrimitive && pickFeature.id && pickFeature.id.type === "yj-dth-build") {
|
||||
if (pickFeature.id.name) {
|
||||
labelText = pickFeature.id.name
|
||||
}
|
||||
}
|
||||
else if (pickFeature.primitive && pickFeature.primitive.id && pickFeature.primitive.id.id && pickFeature.primitive.id.id === 'yj-dth-cover-label') {
|
||||
coverLabelEntity.position = _this.sdk.viewer.scene.pickPosition(e.endPosition)
|
||||
return
|
||||
}
|
||||
else {
|
||||
coverLabelEntity.show = false
|
||||
return
|
||||
}
|
||||
|
||||
if (labelText) {
|
||||
coverLabelEntity.position = _this.sdk.viewer.scene.pickPosition(e.endPosition)
|
||||
coverLabelEntity.label = new Cesium.LabelGraphics({
|
||||
text: labelText,
|
||||
font: "20px Helvetica",
|
||||
pixelOffset: { x: 0, y: -30 },
|
||||
fillColor: Cesium.Color.fromCssColorString('#ffffff'),
|
||||
outlineColor: Cesium.Color.BLACK,
|
||||
outlineWidth: 1,
|
||||
showBackground: true,
|
||||
backgroundColor: Cesium.Color.fromCssColorString('#000000').withAlpha(0.8),
|
||||
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
|
||||
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
||||
})
|
||||
coverLabelEntity.show = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*根据用户信息查询单体化*/
|
||||
queryByUserInfo(data) {
|
||||
this.queryByPoint([data.position.lng, data.position.lat], data.position.alt, data.id)
|
||||
}
|
||||
|
||||
//点查询 点击查询是查询分层的数据
|
||||
async queryByPoint(point) {
|
||||
let url = ""
|
||||
if (this.options.host.endsWith("yjearth4.0")) {
|
||||
url = this.options.host + '/api/v1/dth/build/query_by_point'
|
||||
}
|
||||
else {
|
||||
url = this.options.host + '/yjearth4.0/api/v1/dth/build/query_by_point'
|
||||
}
|
||||
url += '?point=' + JSON.stringify({ 'lng': point[0], 'lat': point[1] })
|
||||
let response = await fetch(url, {
|
||||
method: 'get',
|
||||
// body: JSON.stringify({point: {'lng': point[0],'lat': point[1]}}),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
"token": getToken(),
|
||||
"Authorization": "Bearer " + getToken(),
|
||||
}
|
||||
})
|
||||
if (response.status === 200) {
|
||||
let data = await response.json()
|
||||
if (data.code === 200 || data.code === 0) {
|
||||
this.processQueryByPointResults(data.data)
|
||||
}
|
||||
else {
|
||||
window.ELEMENT && window.ELEMENT.Message({
|
||||
message: data.msg || data.message,
|
||||
type: 'warning',
|
||||
duration: 1500
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 处理查询结果
|
||||
async processQueryByPointResults(data, isflyto, offset = { heading: 0.0, pitch: -90.0, roll: 0.0 }) {
|
||||
data.build_info && this.handlePickEvent(data)
|
||||
let range
|
||||
this.clearAllDthPrimitive()
|
||||
this.clearAllUnitPrimitive()
|
||||
if (this.activeBuilding) {
|
||||
this.clearBuildingPrimitive(this.activeBuilding)
|
||||
this.activeBuilding = null
|
||||
}
|
||||
|
||||
if (data.build_info) {
|
||||
range = JSON.parse(data.build_info.range)
|
||||
if (data.dan_yuan.length > 0) {
|
||||
for (let i = 0; i < data.dan_yuan.length; i++) {
|
||||
if (data.dan_yuan[i].children.length > 0) {
|
||||
this.addDthPrimitive(data.dan_yuan[i].children, data.build_info, data.dan_yuan[i])
|
||||
}
|
||||
else {
|
||||
this.addUnitPrimitive([data.dan_yuan[i]], data.build_info, data.dan_yuan[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.activeBuilding = data.build_info.ID || data.build_info.id
|
||||
this.addBuildingPrimitive([data.build_info])
|
||||
}
|
||||
if (isflyto) {
|
||||
if (data.info && data.info.dan_yuan) {
|
||||
range = JSON.parse(data.info.dan_yuan.range)
|
||||
}
|
||||
if (data.info && data.info.hu) {
|
||||
range = JSON.parse(data.info.hu.range)
|
||||
for (let i = 0; i < range.length; i++) {
|
||||
range[i].alt = data.info.hu.bottom
|
||||
}
|
||||
for (let i = 0; i < this.primitives.dth.length; i++) {
|
||||
await this.primitives.dth[i].readyPromise
|
||||
let primitivesData = this.primitives.dth[i]._primitiveOptions.geometryInstances[0].id
|
||||
if (primitivesData.ID === data.info.hu.ID && primitivesData.room_num === data.info.hu.room_num) {
|
||||
let pickFeature = {
|
||||
id: { ...data.info.hu, build_info: { ...data.build_info }, unit_info: data.info.dan_yuan },
|
||||
primitive: this.primitives.dth[i]
|
||||
}
|
||||
this.getIDBypickFeature(pickFeature)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
this.flyTo(range, offset)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 添加房屋Primitive
|
||||
async addBuildingPrimitive(array) {
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
let fromDegreesArray = []
|
||||
let extrudedHeight = 0
|
||||
let positions = JSON.parse(array[i].range)
|
||||
for (let m = 0; m < positions.length; m++) {
|
||||
if (extrudedHeight < positions[m].alt) {
|
||||
extrudedHeight = positions[m].alt
|
||||
}
|
||||
fromDegreesArray.push(positions[m].lng, positions[m].lat, 0)
|
||||
}
|
||||
let polygonGeometry = new Cesium.PolygonGeometry({
|
||||
polygonHierarchy: new Cesium.PolygonHierarchy(
|
||||
Cesium.Cartesian3.fromDegreesArrayHeights(fromDegreesArray)
|
||||
),
|
||||
// perPositionHeight: true, //使用z坐标 否则高度从0开始
|
||||
extrudedHeight: 100000000, //拉伸高度
|
||||
});
|
||||
this.primitives.building.push(this.sdk.viewer.scene.primitives.add(
|
||||
new Cesium.ClassificationPrimitive({
|
||||
geometryInstances: new Cesium.GeometryInstance({
|
||||
id: {
|
||||
type: 'yj-dth-build',
|
||||
...array[i],
|
||||
},
|
||||
geometry: Cesium.PolygonGeometry.createGeometry(polygonGeometry),
|
||||
attributes: {
|
||||
color: Cesium.ColorGeometryInstanceAttribute.fromColor(
|
||||
Cesium.Color.fromCssColorString('rgb(255, 235, 59, 0.4)')
|
||||
),
|
||||
show: new Cesium.ShowGeometryInstanceAttribute(true),
|
||||
}
|
||||
}),
|
||||
classificationType: Cesium.ClassificationType.CESIUM_3D_TILE,
|
||||
})
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
// 根据id删除房屋Primitive
|
||||
clearBuildingPrimitive(id) {
|
||||
for (let i = this.primitives.building.length - 1; i >= 0; i--) {
|
||||
if (id === this.primitives.building[i]._primitiveOptions.geometryInstances[0].id.ID || id === this.primitives.building[i]._primitiveOptions.geometryInstances[0].id.id) {
|
||||
this.sdk.viewer.scene.primitives.remove(this.primitives.building[i])
|
||||
this.primitives.building.splice(i, 1)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
// 删除全部房屋Primitive
|
||||
clearAllBuildingPrimitive() {
|
||||
for (let i = this.primitives.building.length - 1; i >= 0; i--) {
|
||||
this.sdk.viewer.scene.primitives.remove(this.primitives.building[i])
|
||||
}
|
||||
this.primitives.building = []
|
||||
}
|
||||
|
||||
// 添加单元Primitive
|
||||
async addUnitPrimitive(array, build_info, unit_info) {
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
let fromDegreesArray = []
|
||||
let extrudedHeight = 0
|
||||
let positions = JSON.parse(array[i].range)
|
||||
for (let m = 0; m < positions.length; m++) {
|
||||
if (extrudedHeight < positions[m].alt) {
|
||||
extrudedHeight = positions[m].alt
|
||||
}
|
||||
fromDegreesArray.push(positions[m].lng, positions[m].lat, 0)
|
||||
}
|
||||
let polygonGeometry = new Cesium.PolygonGeometry({
|
||||
polygonHierarchy: new Cesium.PolygonHierarchy(
|
||||
Cesium.Cartesian3.fromDegreesArrayHeights(fromDegreesArray)
|
||||
),
|
||||
// perPositionHeight: true, //使用z坐标 否则高度从0开始
|
||||
extrudedHeight: 100000000, //拉伸高度
|
||||
});
|
||||
this.primitives.unit.push(this.sdk.viewer.scene.primitives.add(
|
||||
new Cesium.ClassificationPrimitive({
|
||||
geometryInstances: new Cesium.GeometryInstance({
|
||||
id: {
|
||||
type: 'yj-dth-unit',
|
||||
...array[i],
|
||||
build_info: { ...build_info },
|
||||
unit_info: { ...unit_info }
|
||||
},
|
||||
geometry: Cesium.PolygonGeometry.createGeometry(polygonGeometry),
|
||||
attributes: {
|
||||
color: Cesium.ColorGeometryInstanceAttribute.fromColor(
|
||||
Cesium.Color.fromCssColorString('rgb(255, 235, 59, 0.4)')
|
||||
),
|
||||
show: new Cesium.ShowGeometryInstanceAttribute(true),
|
||||
}
|
||||
}),
|
||||
classificationType: Cesium.ClassificationType.CESIUM_3D_TILE,
|
||||
})
|
||||
))
|
||||
this.primitives.unit.push(this.sdk.viewer.scene.primitives.add(
|
||||
new Cesium.GroundPolylinePrimitive({
|
||||
geometryInstances: new Cesium.GeometryInstance({
|
||||
geometry: new Cesium.GroundPolylineGeometry({
|
||||
positions: Cesium.Cartesian3.fromDegreesArrayHeights(fromDegreesArray),
|
||||
width: 2.0
|
||||
}),
|
||||
attributes: {
|
||||
color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.fromCssColorString('#00ff0a').withAlpha(0.8))
|
||||
},
|
||||
}),
|
||||
appearance: new Cesium.PolylineColorAppearance()
|
||||
})
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
// 根据id删除单元Primitive
|
||||
clearUnitPrimitive(id) {
|
||||
for (let i = this.primitives.building.length - 1; i >= 0; i--) {
|
||||
if (id === this.primitives.building[i]._primitiveOptions.geometryInstances[0].id.ID || id === this.primitives.building[i]._primitiveOptions.geometryInstances[0].id.id) {
|
||||
this.sdk.viewer.scene.primitives.remove(this.primitives.unit[i])
|
||||
this.primitives.unit.splice(i, 1)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 删除全部单元Primitive
|
||||
clearAllUnitPrimitive() {
|
||||
for (let i = this.primitives.unit.length - 1; i >= 0; i--) {
|
||||
this.sdk.viewer.scene.primitives.remove(this.primitives.unit[i])
|
||||
}
|
||||
this.primitives.unit = []
|
||||
}
|
||||
|
||||
// 添加单体化Primitive
|
||||
addDthPrimitive(array, build_info, unit_info) {
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
let positions = JSON.parse(array[i].range)
|
||||
let fromDegreesArray = []
|
||||
for (let m = 0; m < positions.length; m++) {
|
||||
fromDegreesArray.push(positions[m].lng, positions[m].lat, array[i].bottom + 0.3)
|
||||
}
|
||||
let polygonGeometry = new Cesium.PolygonGeometry({
|
||||
polygonHierarchy: new Cesium.PolygonHierarchy(
|
||||
Cesium.Cartesian3.fromDegreesArrayHeights(fromDegreesArray)
|
||||
),
|
||||
perPositionHeight: true, //使用z坐标 否则高度从0开始
|
||||
extrudedHeight: array[i].height + array[i].bottom, //拉伸高度
|
||||
});
|
||||
let polygonGeometryBorder = new Cesium.PolygonGeometry({
|
||||
polygonHierarchy: new Cesium.PolygonHierarchy(
|
||||
Cesium.Cartesian3.fromDegreesArrayHeights(fromDegreesArray)
|
||||
),
|
||||
perPositionHeight: true, //使用z坐标 否则高度从0开始
|
||||
extrudedHeight: array[i].bottom, //拉伸高度
|
||||
});
|
||||
this.primitives.dth.push(this.sdk.viewer.scene.primitives.add(
|
||||
new Cesium.ClassificationPrimitive({
|
||||
geometryInstances: new Cesium.GeometryInstance({
|
||||
id: {
|
||||
type: 'yj-dth-dth',
|
||||
...array[i],
|
||||
build_info: { ...build_info },
|
||||
unit_info: { ...unit_info }
|
||||
},
|
||||
geometry: Cesium.PolygonGeometry.createGeometry(polygonGeometry),
|
||||
attributes: {
|
||||
color: Cesium.ColorGeometryInstanceAttribute.fromColor(
|
||||
Cesium.Color.fromCssColorString('rgb(0, 64, 255, 0.4)')
|
||||
),
|
||||
show: new Cesium.ShowGeometryInstanceAttribute(true),
|
||||
}
|
||||
}),
|
||||
classificationType: Cesium.ClassificationType.CESIUM_3D_TILE,
|
||||
})
|
||||
));
|
||||
this.primitives.dth.push(this.sdk.viewer.scene.primitives.add(
|
||||
new Cesium.ClassificationPrimitive({
|
||||
geometryInstances: new Cesium.GeometryInstance({
|
||||
id: {
|
||||
type: 'yj-dth-dth-border',
|
||||
...array[i],
|
||||
},
|
||||
geometry: Cesium.PolygonGeometry.createGeometry(polygonGeometryBorder),
|
||||
attributes: {
|
||||
color: Cesium.ColorGeometryInstanceAttribute.fromColor(
|
||||
Cesium.Color.fromCssColorString('rgb(0, 0, 0, 1)')
|
||||
),
|
||||
show: new Cesium.ShowGeometryInstanceAttribute(true),
|
||||
}
|
||||
}),
|
||||
classificationType: Cesium.ClassificationType.CESIUM_3D_TILE,
|
||||
})
|
||||
));
|
||||
}
|
||||
}
|
||||
// 根据id删除单体化Primitive
|
||||
clearDthPrimitive(id) {
|
||||
for (let i = this.primitives.dth.length - 1; i >= 0; i--) {
|
||||
if (id === this.primitives.dth[i]._primitiveOptions.geometryInstances[0].id.ID || id === this.primitives.dth[i]._primitiveOptions.geometryInstances[0].id.id) {
|
||||
this.sdk.viewer.scene.primitives.remove(this.primitives.dth[i])
|
||||
this.primitives.dth.splice(i, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 删除全部单体化Primitive
|
||||
clearAllDthPrimitive() {
|
||||
this.highlightPrimitive && this.sdk.viewer.scene.primitives.remove(this.highlightPrimitive)
|
||||
for (let i = this.primitives.dth.length - 1; i >= 0; i--) {
|
||||
this.sdk.viewer.scene.primitives.remove(this.primitives.dth[i])
|
||||
}
|
||||
this.primitives.dth = []
|
||||
}
|
||||
|
||||
getIDBypickFeature(pickFeature) {
|
||||
//恢复上一个贴对象面显示
|
||||
if (this.clickHighlightPrimitive) {
|
||||
this.clickHighlightPrimitive.show = true;
|
||||
}
|
||||
this.highlightPrimitive && this.sdk.viewer.scene.primitives.remove(this.highlightPrimitive)
|
||||
this.highlightPrimitive = this.sdk.viewer.scene.primitives.add(
|
||||
new Cesium.ClassificationPrimitive({
|
||||
geometryInstances: new Cesium.GeometryInstance({
|
||||
id: {
|
||||
...pickFeature.id,
|
||||
type: 'yj-dth-highlight',
|
||||
|
||||
},
|
||||
geometry: pickFeature.primitive._primitiveOptions.geometryInstances[0].geometry,
|
||||
attributes: {
|
||||
color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.fromCssColorString('#ff9800').withAlpha(0.8)),
|
||||
show: new Cesium.ShowGeometryInstanceAttribute(true),
|
||||
}
|
||||
}),
|
||||
classificationType: Cesium.ClassificationType.CESIUM_3D_TILE,
|
||||
})
|
||||
)
|
||||
this.highlightPrimitive.readyPromise.then(() => {
|
||||
//设置当前点击的贴对象面不显示
|
||||
pickFeature.primitive.show = false;
|
||||
})
|
||||
this.clickHighlightPrimitive = pickFeature.primitive;
|
||||
|
||||
let range = pickFeature.id.range
|
||||
if (typeof pickFeature.id.range === 'string') {
|
||||
range = JSON.parse(pickFeature.id.range)
|
||||
}
|
||||
this.getHilightArea(range)
|
||||
this.handlePickEvent(pickFeature.id)
|
||||
}
|
||||
|
||||
//处理点击事件
|
||||
handlePickEvent(id) {
|
||||
this.PickBuildingEvent.raiseEvent(id); //触发选中事件 通知界面更新
|
||||
}
|
||||
|
||||
getHilightArea(points, radius = 1) {
|
||||
let arr = []
|
||||
points.forEach((point) => {
|
||||
arr.push([(point.lng), (point.lat)])
|
||||
})
|
||||
arr.push(arr[0])
|
||||
var poly = turf.polygon([arr])
|
||||
var buffered = turf.buffer(poly, Number(radius) / 1000)
|
||||
return buffered.geometry.coordinates
|
||||
}
|
||||
|
||||
async flyTo(positions, offset = { heading: 0.0, pitch: -90.0, roll: 0.0 }) {
|
||||
let tools = new YJ.Tools(this.sdk)
|
||||
let height = 0
|
||||
let positionArray = []
|
||||
for (let i = 0; i < positions.length; i++) {
|
||||
if (positions[i].alt) {
|
||||
height = positions[i].alt
|
||||
}
|
||||
else {
|
||||
height = await tools.getClampToHeight(positions[i])
|
||||
}
|
||||
let a = Cesium.Cartesian3.fromDegrees(positions[i].lng, positions[i].lat, height)
|
||||
positionArray.push(a.x, a.y, a.z)
|
||||
}
|
||||
let BoundingSphere = await Cesium.BoundingSphere.fromVertices(positionArray)
|
||||
this.sdk.viewer.camera.flyToBoundingSphere(BoundingSphere, {
|
||||
offset: {
|
||||
heading: Cesium.Math.toRadians(offset.heading || 0),
|
||||
pitch: Cesium.Math.toRadians((offset.pitch || offset.pitch === 0) ? offset.pitch : -90),
|
||||
roll: Cesium.Math.toRadians(offset.roll || 0)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
activate() {
|
||||
this.isActivate = true;
|
||||
}
|
||||
|
||||
deactivate() {
|
||||
this.isActivate = false;
|
||||
}
|
||||
}
|
||||
|
||||
export default DTH
|
||||
267
src/Global/DTH/index1.js
Normal file
267
src/Global/DTH/index1.js
Normal file
@ -0,0 +1,267 @@
|
||||
import { getHost, getToken } from "../../on";
|
||||
class DTH {
|
||||
constructor(sdk, options = {}) {
|
||||
this.sdk = sdk
|
||||
this.primitives = {
|
||||
building: [],
|
||||
dth: []
|
||||
}
|
||||
this.options = {...options}
|
||||
this.options.host = this.options.host || getHost()
|
||||
this.temporaryDth = []
|
||||
this.dth = {}
|
||||
this.HandlePickHouseEvent = new Cesium.Event();
|
||||
this.initEvents()
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 注册分户点击的事件回调
|
||||
* @memberOf DTH
|
||||
* */
|
||||
houseSelectedCallback(that, cb) {
|
||||
this.HandlePickHouseEvent.addEventListener(
|
||||
cb,
|
||||
that
|
||||
)
|
||||
}
|
||||
|
||||
//场景事件
|
||||
initEvents() {
|
||||
new Cesium.ScreenSpaceEventHandler(this.sdk.viewer.scene.canvas).setInputAction(((e) => {
|
||||
if (!this.isActivate) return;
|
||||
let pickFeature = this.sdk.viewer.scene.pick(e.position);
|
||||
if (pickFeature) {
|
||||
//点击了已有的分户单体化
|
||||
if (pickFeature.primitive && pickFeature.primitive instanceof Cesium.ClassificationPrimitive && pickFeature.id && pickFeature.id.type == "dth") {
|
||||
this.getIDBypickFeature(pickFeature); //处理点击到的楼层
|
||||
return;
|
||||
}
|
||||
|
||||
if (pickFeature.id && pickFeature.id.type === 'highlight') {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.highlightPrimitive && this.sdk.viewer.scene.primitives.remove(this.highlightPrimitive)
|
||||
let position = this.sdk.viewer.scene.pickPosition(e.position); //屏幕坐标转为笛卡尔空间坐标
|
||||
if (!position) return;
|
||||
|
||||
let c = Cesium.Cartographic.fromCartesian(position); //笛卡尔坐标转为经纬度(弧度)
|
||||
let point = [Cesium.Math.toDegrees(c.longitude), Cesium.Math.toDegrees(c.latitude)]; //转为经纬度点
|
||||
this.queryByPoint(point, c.height);
|
||||
}), Cesium.ScreenSpaceEventType.LEFT_CLICK);
|
||||
}
|
||||
|
||||
/*根据用户信息查询单体化*/
|
||||
queryByUserInfo(data) {
|
||||
this.queryByPoint([data.position.lng, data.position.lat], data.position.alt, data.id)
|
||||
}
|
||||
|
||||
//点查询 点击查询是查询分层的数据
|
||||
async queryByPoint(point) {
|
||||
let url = ""
|
||||
if (this.options.host.endsWith("yjearth4.0")) {
|
||||
url = this.options.host + '/api/v1/dth/query_by_point'
|
||||
}
|
||||
else {
|
||||
url = this.options.host + '/yjearth4.0/api/v1/dth/query_by_point'
|
||||
}
|
||||
url += '?point=' + JSON.stringify({'lng': point[0],'lat': point[1]})
|
||||
let response = await fetch(url, {
|
||||
method: 'get',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
"token": getToken(),
|
||||
"Authorization": "Bearer " + getToken(),
|
||||
}
|
||||
})
|
||||
if (response.status === 200) {
|
||||
let data = await response.json()
|
||||
if (data.code === 200 || data.code === 0) {
|
||||
this.clearAllDthPrimitive()
|
||||
this.addDthPrimitive(data.data.list)
|
||||
}
|
||||
else {
|
||||
window.ELEMENT && window.ELEMENT.Message({
|
||||
message: data.msg || data.message,
|
||||
type: 'warning',
|
||||
duration: 1500
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 添加房屋Primitive
|
||||
async addBuildingPrimitive(array) {
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
let fromDegreesArray = []
|
||||
let extrudedHeight = 0
|
||||
let positions = JSON.parse(array[i].range)
|
||||
for (let m = 0; m < positions.length; m++) {
|
||||
if (extrudedHeight < positions[m].alt) {
|
||||
extrudedHeight = positions[m].alt
|
||||
}
|
||||
fromDegreesArray.push(positions[m].lng, positions[m].lat, 0)
|
||||
}
|
||||
let polygonGeometry = new Cesium.PolygonGeometry({
|
||||
polygonHierarchy: new Cesium.PolygonHierarchy(
|
||||
Cesium.Cartesian3.fromDegreesArrayHeights(fromDegreesArray)
|
||||
),
|
||||
// perPositionHeight: true, //使用z坐标 否则高度从0开始
|
||||
extrudedHeight: 100000000, //拉伸高度
|
||||
});
|
||||
this.primitives.building.push(this.sdk.viewer.scene.primitives.add(
|
||||
new Cesium.ClassificationPrimitive({
|
||||
geometryInstances: new Cesium.GeometryInstance({
|
||||
id: {
|
||||
...array[i],
|
||||
},
|
||||
geometry: Cesium.PolygonGeometry.createGeometry(polygonGeometry),
|
||||
attributes: {
|
||||
color: Cesium.ColorGeometryInstanceAttribute.fromColor(
|
||||
Cesium.Color.fromCssColorString('rgb(255, 235, 59, 0.4)')
|
||||
),
|
||||
show: new Cesium.ShowGeometryInstanceAttribute(true),
|
||||
}
|
||||
}),
|
||||
classificationType: Cesium.ClassificationType.CESIUM_3D_TILE,
|
||||
}), 0
|
||||
))
|
||||
}
|
||||
}
|
||||
// 根据id删除房屋Primitive
|
||||
clearBuildingPrimitive(id) {
|
||||
for (let i = this.primitives.building.length - 1; i >= 0; i--) {
|
||||
if (id === this.primitives.building[i]._primitiveOptions.geometryInstances[0].id.ID) {
|
||||
this.sdk.viewer.scene.primitives.remove(this.primitives.building[i])
|
||||
this.primitives.building.splice(i, 1)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
// 删除全部房屋Primitive
|
||||
clearAllBuildingPrimitive() {
|
||||
for (let i = this.primitives.building.length - 1; i >= 0; i--) {
|
||||
this.sdk.viewer.scene.primitives.remove(this.primitives.building[i])
|
||||
}
|
||||
this.primitives.building = []
|
||||
}
|
||||
|
||||
// 添加单体化Primitive
|
||||
addDthPrimitive(array) {
|
||||
let readyIndex = 0
|
||||
let Primitives = []
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
let positions = JSON.parse(array[i].range)
|
||||
let fromDegreesArray = []
|
||||
for (let m = 0; m < positions.length; m++) {
|
||||
fromDegreesArray.push(positions[m].lng, positions[m].lat, array[i].bottom)
|
||||
}
|
||||
let polygonGeometry = new Cesium.PolygonGeometry({
|
||||
polygonHierarchy: new Cesium.PolygonHierarchy(
|
||||
Cesium.Cartesian3.fromDegreesArrayHeights(fromDegreesArray)
|
||||
),
|
||||
perPositionHeight: true, //使用z坐标 否则高度从0开始
|
||||
extrudedHeight: array[i].height + array[i].bottom, //拉伸高度
|
||||
});
|
||||
let Primitive = new Cesium.ClassificationPrimitive({
|
||||
geometryInstances: new Cesium.GeometryInstance({
|
||||
id: {
|
||||
type: 'dth',
|
||||
...array[i],
|
||||
},
|
||||
geometry: Cesium.PolygonGeometry.createGeometry(polygonGeometry),
|
||||
attributes: {
|
||||
color: Cesium.ColorGeometryInstanceAttribute.fromColor(
|
||||
Cesium.Color.fromCssColorString('rgb(255, 235, 59, 0.4)')
|
||||
),
|
||||
show: new Cesium.ShowGeometryInstanceAttribute(true),
|
||||
}
|
||||
}),
|
||||
classificationType: Cesium.ClassificationType.CESIUM_3D_TILE,
|
||||
})
|
||||
Primitives.push(Primitive)
|
||||
this.sdk.viewer.scene.primitives.add(Primitive)
|
||||
Primitive._readyPromise.then(()=>{
|
||||
this.clearDthPrimitive(Primitive._primitiveOptions.geometryInstances[0].id.ID)
|
||||
readyIndex ++
|
||||
if(readyIndex >= array.length) {
|
||||
this.primitives.dth.push(...Primitives);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
// 根据id删除单体化Primitive
|
||||
clearDthPrimitive(id) {
|
||||
for (let i = this.primitives.dth.length - 1; i >= 0; i--) {
|
||||
if (id === this.primitives.dth[i]._primitiveOptions.geometryInstances[0].id.ID) {
|
||||
this.sdk.viewer.scene.primitives.remove(this.primitives.dth[i])
|
||||
this.primitives.dth.splice(i, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getDthPrimitive(id) {
|
||||
for (let i = this.primitives.dth.length - 1; i >= 0; i--) {
|
||||
if (id === this.primitives.dth[i]._primitiveOptions.geometryInstances[0].id.ID) {
|
||||
return this.primitives.dth[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 删除全部单体化Primitive
|
||||
clearAllDthPrimitive() {
|
||||
for (let i = this.primitives.dth.length - 1; i >= 0; i--) {
|
||||
this.sdk.viewer.scene.primitives.remove(this.primitives.dth[i])
|
||||
}
|
||||
this.primitives.dth = []
|
||||
}
|
||||
|
||||
getIDBypickFeature(pickFeature) {
|
||||
//恢复上一个贴对象面显示
|
||||
if (this.clickHighlightPrimitive) {
|
||||
this.clickHighlightPrimitive.show = true;
|
||||
}
|
||||
this.highlightPrimitive && this.sdk.viewer.scene.primitives.remove(this.highlightPrimitive)
|
||||
this.highlightPrimitive = this.sdk.viewer.scene.primitives.add(
|
||||
new Cesium.ClassificationPrimitive({
|
||||
geometryInstances: new Cesium.GeometryInstance({
|
||||
id: {
|
||||
type: 'highlight',
|
||||
},
|
||||
geometry: pickFeature.primitive._primitiveOptions.geometryInstances[0].geometry,
|
||||
attributes: {
|
||||
color: Cesium.ColorGeometryInstanceAttribute.fromColor(
|
||||
Cesium.Color.fromCssColorString('rgb(255, 0, 0, 1)')
|
||||
),
|
||||
show: new Cesium.ShowGeometryInstanceAttribute(true),
|
||||
}
|
||||
}),
|
||||
classificationType: Cesium.ClassificationType.CESIUM_3D_TILE,
|
||||
})
|
||||
)
|
||||
this.highlightPrimitive.readyPromise.then(() => {
|
||||
//设置当前点击的贴对象面不显示
|
||||
pickFeature.primitive.show = false;
|
||||
})
|
||||
this.clickHighlightPrimitive = pickFeature.primitive;
|
||||
this.handlePickHouse(pickFeature.id)
|
||||
}
|
||||
|
||||
//处理拾取到的户室信息
|
||||
handlePickHouse(id) {
|
||||
this.HandlePickHouseEvent.raiseEvent({}); //触发选中事件 通知界面更新
|
||||
}
|
||||
|
||||
activate() {
|
||||
this.isActivate = true;
|
||||
}
|
||||
|
||||
deactivate() {
|
||||
this.isActivate = false;
|
||||
}
|
||||
}
|
||||
|
||||
export default DTH
|
||||
53
src/Global/ExportKml/index.js
Normal file
53
src/Global/ExportKml/index.js
Normal file
@ -0,0 +1,53 @@
|
||||
/**
|
||||
* @name: index
|
||||
* @author: Administrator
|
||||
* @date: 2023-09-11 16:41
|
||||
* @description:index
|
||||
* @update: 2023-09-11 16:41
|
||||
*/
|
||||
import BillboardObject from "../../Obj/Base/BillboardObject";
|
||||
import PolygonObject from "../../Obj/Base/PolygonObject";
|
||||
import PolylineObject from "../../Obj/Base/PolylineObject";
|
||||
import Circle from "../../Obj/Base/CircleDiffuse";
|
||||
|
||||
function exportKml(list = []) {
|
||||
|
||||
let entities = new Cesium.EntityCollection();
|
||||
list.forEach(entity => {
|
||||
if (
|
||||
entity instanceof BillboardObject ||
|
||||
entity instanceof PolygonObject ||
|
||||
entity instanceof Circle ||
|
||||
entity instanceof PolylineObject
|
||||
) {
|
||||
entities.add(entity.entity)
|
||||
}
|
||||
})
|
||||
if (entities.values.length) {
|
||||
let promise = Cesium.exportKml({entities})
|
||||
promise.then(e => {
|
||||
// Cesium.exportKml(e.kml,)
|
||||
funDownload(e.kml, new Date().getTime() + ".kml")
|
||||
})
|
||||
} else {
|
||||
console.error("允许导出为kml的对象为空")
|
||||
}
|
||||
}
|
||||
|
||||
function funDownload(content, filename) {
|
||||
let eleLink = document.createElement("a");
|
||||
eleLink.download = filename;
|
||||
eleLink.style.display = "none";
|
||||
// 字符内容转变成blob地址
|
||||
let blob = new Blob([content]);
|
||||
eleLink.href = URL.createObjectURL(blob);
|
||||
// 触发点击
|
||||
document.body.appendChild(eleLink);
|
||||
eleLink.click();
|
||||
// 然后移除
|
||||
document.body.removeChild(eleLink);
|
||||
}
|
||||
|
||||
|
||||
export default exportKml
|
||||
|
||||
67
src/Global/FlyRoam/_element.js
Normal file
67
src/Global/FlyRoam/_element.js
Normal file
@ -0,0 +1,67 @@
|
||||
function html() {
|
||||
return `
|
||||
<span class="custom-divider"></span>
|
||||
<div class="div-item">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<span class="label">名称</span>
|
||||
<input class="input" type="text" name="name">
|
||||
</div>
|
||||
<div class="col"></div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="custom-divider"></span>
|
||||
<div class="div-item">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<input type="checkbox" name="isTotalTime" style="width: 16px; line-height: 15px; height: 15px; cursor: pointer; width: auto; margin-right: 5px;">
|
||||
<span class="label">设置总时长</span>
|
||||
<div class="input-number input-number-unit-3">
|
||||
<input class="input total-time" type="number" title="" min="0" max="999999.99" step="0.01" name="totalTime" value="0">
|
||||
<span class="unit" style="top: 6px;">秒(s)</span>
|
||||
<span class="arrow"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<input type="checkbox" name="repeat" style="width: 16px; line-height: 15px; height: 15px; cursor: pointer; width: auto; margin-right: 5px;">
|
||||
<span class="label">是否循环播放</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="custom-divider"></span>
|
||||
<div class="div-item">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<button class="add-point"><svg class="icon-add"><use xlink:href="#yj-icon-add"></use></svg>增加视点</button>
|
||||
</div>
|
||||
<div class="col">
|
||||
<button class="modify-point"><svg class="icon-edit"><use xlink:href="#yj-icon-edit"></use></svg>调整视点</button>
|
||||
</div>
|
||||
<div class="col">
|
||||
<button class="afreshPlay"><svg class="icon-play"><use xlink:href="#yj-icon-play"></use></svg>播放</button>
|
||||
</div>
|
||||
<div class="col">
|
||||
<button class="cease"><svg class="icon-pause"><use xlink:href="#yj-icon-pause"></use></svg>结束</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table">
|
||||
<div class="table-head">
|
||||
<div class="tr">
|
||||
<div class="th">序号</div>
|
||||
<div class="th">时长(s)</div>
|
||||
<div class="th">操作</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-body">
|
||||
<div class="table-empty">
|
||||
<div class="empty-img"></div>
|
||||
<p>暂无数据</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="custom-divider"></span>
|
||||
`
|
||||
}
|
||||
|
||||
export { html }
|
||||
389
src/Global/FlyRoam/index.js
Normal file
389
src/Global/FlyRoam/index.js
Normal file
@ -0,0 +1,389 @@
|
||||
|
||||
/**
|
||||
* @description 飞行漫游
|
||||
*/
|
||||
import Dialog from '../../BaseDialog';
|
||||
import { html } from "./_element";
|
||||
import Tools from "../../Tools";
|
||||
import { closeRotateAround, closeViewFollow} from '../../Global/global'
|
||||
let _DialogObject = null
|
||||
let clickHandler
|
||||
let repeat = 0
|
||||
let currentRepeat = 0
|
||||
|
||||
|
||||
const open = async (sdk, options = {}, _Dialog = {}) => {
|
||||
let name = options.name || '漫游路径'
|
||||
options.points || (options.points = [])
|
||||
if(options.repeat) {
|
||||
repeat = Number(options.repeat)
|
||||
}
|
||||
let viewer = sdk.viewer
|
||||
let tools = new Tools(sdk)
|
||||
let active = 0
|
||||
|
||||
if (_DialogObject && _DialogObject.close) {
|
||||
_DialogObject.close()
|
||||
_DialogObject = null
|
||||
}
|
||||
|
||||
_DialogObject = await new Dialog(viewer._container, {
|
||||
title: '飞行漫游', left: '180px', top: '100px',
|
||||
closeCallBack: () => {
|
||||
cease({ viewer })
|
||||
},
|
||||
})
|
||||
await _DialogObject.init()
|
||||
let contentElm = document.createElement('div');
|
||||
contentElm.className = 'fly-roam'
|
||||
contentElm.innerHTML = html()
|
||||
_DialogObject.contentAppChild(contentElm)
|
||||
|
||||
let all_elm = contentElm.getElementsByTagName("*")
|
||||
// EventBinding(all_elm)
|
||||
|
||||
let tableBody = contentElm.getElementsByClassName('table-body')[0];
|
||||
let tableEmpty = contentElm.getElementsByClassName('table-empty')[0]
|
||||
|
||||
let handler = {
|
||||
set: function (target, prop, value) {
|
||||
target[prop] = value;
|
||||
if (target.length > 0) {
|
||||
tableEmpty.style.display = 'none'
|
||||
}
|
||||
else {
|
||||
tableEmpty.style.display = 'flex'
|
||||
}
|
||||
return true;
|
||||
},
|
||||
};
|
||||
let i = 0
|
||||
let points = new Proxy([], handler);
|
||||
for (i = 0; i < options.points.length; i++) {
|
||||
points.push(options.points[i])
|
||||
addTrElm(options.points[i])
|
||||
}
|
||||
|
||||
|
||||
// let nameImputBoxElm = contentElm.getElementsByClassName('input-box')[0]
|
||||
// check(nameImputBoxElm, { validator: 'notEmpty', message: '名称不能为空!', trigger: 'input' })
|
||||
let nameElm = contentElm.querySelector("input[name='name']")
|
||||
nameElm.value = name
|
||||
nameElm.addEventListener('input', () => {
|
||||
name = nameElm.value
|
||||
})
|
||||
|
||||
let addListBtn = document.createElement('button');
|
||||
addListBtn.innerHTML = '保存'
|
||||
addListBtn.addEventListener('click', () => {
|
||||
if (!name) {
|
||||
name = '漫游路径'
|
||||
nameElm.value = name
|
||||
}
|
||||
let newPoints = []
|
||||
points.map((item) => {
|
||||
newPoints.push(item)
|
||||
})
|
||||
_Dialog.clickSavePath && _Dialog.clickSavePath(
|
||||
{
|
||||
name: name,
|
||||
points: newPoints,
|
||||
repeat: repeat+''
|
||||
}
|
||||
)
|
||||
})
|
||||
_DialogObject.footAppChild(addListBtn)
|
||||
|
||||
let endBtn = contentElm.getElementsByClassName('cease')[0]
|
||||
endBtn.addEventListener('click', () => {
|
||||
viewer.camera.cancelFlight()
|
||||
})
|
||||
|
||||
let flyBtn = contentElm.getElementsByClassName('afreshPlay')[0]
|
||||
flyBtn.addEventListener('click', () => {
|
||||
if (points.length > 0) {
|
||||
flyTo(sdk, points, 0)
|
||||
}
|
||||
})
|
||||
|
||||
let addBtn = contentElm.getElementsByClassName('add-point')[0]
|
||||
addBtn.addEventListener('click', () => {
|
||||
let position = tools.cartesian3Towgs84(viewer.camera.position, viewer)
|
||||
let time = 0
|
||||
let data = {
|
||||
duration: time,
|
||||
position: position,
|
||||
orientation: {
|
||||
heading: viewer.camera.heading,
|
||||
pitch: viewer.camera.pitch,
|
||||
roll: viewer.camera.roll
|
||||
}
|
||||
}
|
||||
points.splice(active, 0, data)
|
||||
addTrElm(data)
|
||||
i++
|
||||
})
|
||||
let modifyBtn = contentElm.getElementsByClassName('modify-point')[0]
|
||||
modifyBtn.addEventListener('click', () => {
|
||||
if (!active) {
|
||||
return
|
||||
}
|
||||
let position = tools.cartesian3Towgs84(viewer.camera.position, viewer)
|
||||
points[active - 1].position = position
|
||||
points[active - 1].orientation = {
|
||||
heading: viewer.camera.heading,
|
||||
pitch: viewer.camera.pitch,
|
||||
roll: viewer.camera.roll
|
||||
}
|
||||
})
|
||||
|
||||
let totalTimeElm = contentElm.querySelector("input[name='totalTime']")
|
||||
let isTotalTimeElm = contentElm.querySelector("input[name='isTotalTime']")
|
||||
let repeatElm = contentElm.querySelector("input[name='repeat']")
|
||||
isTotalTimeElm.addEventListener('change', () => {
|
||||
let trList = tableBody.getElementsByClassName('tr')
|
||||
if (isTotalTimeElm.checked && trList.length > 0) {
|
||||
let time = Number((Number(totalTimeElm.value) / (trList.length - 1)).toFixed(2))
|
||||
for (let i = 0; i < trList.length - 1; i++) {
|
||||
points[i].duration = time
|
||||
trList[i].querySelector("input[name='time']").value = time
|
||||
}
|
||||
trList[trList.length - 1].querySelector("input[name='time']").value = 0
|
||||
}
|
||||
})
|
||||
totalTimeElm.addEventListener('blur', () => {
|
||||
let trList = tableBody.getElementsByClassName('tr')
|
||||
totalTimeElm.value = Number(totalTimeElm.value)
|
||||
if (totalTimeElm.value < 0) {
|
||||
totalTimeElm.value = 0
|
||||
}
|
||||
if (isTotalTimeElm.checked && trList.length > 0) {
|
||||
let time = Number((Number(totalTimeElm.value) / (trList.length - 1)).toFixed(2))
|
||||
for (let i = 0; i < trList.length - 1; i++) {
|
||||
points[i].duration = time
|
||||
trList[i].querySelector("input[name='time']").value = time
|
||||
}
|
||||
trList[trList.length - 1].querySelector("input[name='time']").value = 0
|
||||
}
|
||||
})
|
||||
repeatElm.checked = (repeat === Infinity ? true : false)
|
||||
repeatElm.addEventListener('change', () => {
|
||||
if (repeatElm.checked) {
|
||||
repeat = Infinity
|
||||
}
|
||||
else {
|
||||
repeat = 0
|
||||
}
|
||||
currentRepeat = repeat
|
||||
_Dialog.changeRepeatStateCallBack && _Dialog.changeRepeatStateCallBack(repeatElm.checked)
|
||||
})
|
||||
|
||||
// Object.defineProperty(options, 'points', {
|
||||
// get() {
|
||||
// return e_allArea.value
|
||||
// },
|
||||
// set(value) {
|
||||
// e_allArea.value = value
|
||||
// }
|
||||
// })
|
||||
|
||||
function addTrElm(data) {
|
||||
let trList = tableBody.getElementsByClassName('tr')
|
||||
if (trList.length > 0) {
|
||||
trList[trList.length - 1].querySelector("input[name='time']").disabled = undefined
|
||||
}
|
||||
let tr_active = tableBody.getElementsByClassName('tr active')[0]
|
||||
tr_active && (tr_active.className = 'tr')
|
||||
let tr = document.createElement('div');
|
||||
tr.className = 'tr active'
|
||||
tr.innerHTML = `
|
||||
<div class="td" style="justify-content: center;">视点${i + 1}</div>
|
||||
<div class="td">
|
||||
<input class="input time" type="number" title="" min="0" max="999.99" step="0.01" name="time" value="${data.duration}">
|
||||
</div>
|
||||
<div class="td action">
|
||||
<button class="play">播放</span>
|
||||
<button class="delete">删除</span>
|
||||
</div>
|
||||
`
|
||||
tr.addEventListener('click', (v) => {
|
||||
if (v.target.parentNode === tr) {
|
||||
let tr_active = tableBody.getElementsByClassName('tr active')[0]
|
||||
tr_active && (tr_active.className = 'tr')
|
||||
tr.className = 'tr active'
|
||||
for (let m = 0; m < trList.length; m++) {
|
||||
if (trList[m] === tr) {
|
||||
active = m + 1
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
tr.addEventListener('dblclick', (v) => {
|
||||
if (v.target.parentNode === tr) {
|
||||
for (let m = 0; m < trList.length; m++) {
|
||||
if (trList[m] === tr) {
|
||||
viewer.camera.flyTo({
|
||||
destination: Cesium.Cartesian3.fromDegrees(points[m].position.lng, points[m].position.lat, points[m].position.alt),
|
||||
orientation: points[m].orientation,
|
||||
duration: 1
|
||||
})
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
let e_play = tr.getElementsByClassName('play')[0]
|
||||
let e_delete = tr.getElementsByClassName('delete')[0]
|
||||
let e_time = tr.querySelector("input[name='time']")
|
||||
e_play.addEventListener('click', () => {
|
||||
for (let m = 0; m < trList.length; m++) {
|
||||
if (trList[m] === e_delete.parentNode.parentNode) {
|
||||
flyTo(sdk, points, m)
|
||||
}
|
||||
}
|
||||
})
|
||||
e_delete.addEventListener("click", (v) => {
|
||||
for (let m = 0; m < trList.length; m++) {
|
||||
if (trList[m] === e_delete.parentNode.parentNode) {
|
||||
points.splice(m, 1)
|
||||
points[points.length-1] && (points[points.length-1].duration = 0)
|
||||
tableBody.removeChild(tr)
|
||||
if (active > m + 1) {
|
||||
active--
|
||||
trList[active - 1].className = 'tr active'
|
||||
}
|
||||
else if (active == m + 1) {
|
||||
if (trList.length == m) {
|
||||
active -= 1
|
||||
}
|
||||
if (trList.length != 0) {
|
||||
trList[active - 1].className = 'tr active'
|
||||
}
|
||||
}
|
||||
// else if(active == m) {
|
||||
// console.log(trList.length-1, active)
|
||||
// if (trList.length == active-1) {
|
||||
// trList[active-2].className = 'tr active'
|
||||
// }
|
||||
// else {
|
||||
// trList[active-1].className = 'tr active'
|
||||
// }
|
||||
// }
|
||||
if (trList.length > 0) {
|
||||
let lastElm = trList[trList.length - 1].querySelector("input[name='time']")
|
||||
lastElm.disabled = 'disabled'
|
||||
lastElm.value = 0
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
// points.splice(i, 1)
|
||||
// tableBody.removeChild(tr)
|
||||
// if (trList.length > 0) {
|
||||
// trList[trList.length - 1].querySelector("input[name='time']").disabled = 'disabled'
|
||||
// }
|
||||
})
|
||||
e_time.addEventListener('input', (v) => {
|
||||
isTotalTimeElm.checked = false
|
||||
data.duration = Number(e_time.value)
|
||||
if (data.duration < 0) {
|
||||
data.duration = 0
|
||||
}
|
||||
})
|
||||
e_time.addEventListener('blur', () => {
|
||||
e_time.value = Number(Number(e_time.value).toFixed(2))
|
||||
if (e_time.value < 0) {
|
||||
e_time.value = 0
|
||||
}
|
||||
});
|
||||
tableBody.insertBefore(tr, trList[active])
|
||||
active++
|
||||
trList[trList.length - 1].querySelector("input[name='time']").disabled = 'disabled'
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
const close = () => {
|
||||
if (_DialogObject && _DialogObject.close) {
|
||||
_DialogObject.close()
|
||||
_DialogObject = null
|
||||
}
|
||||
}
|
||||
|
||||
const executeFlyTo = (sdk, points = [], index = 0, noStart) => {
|
||||
if (clickHandler) {
|
||||
clickHandler.destroy()
|
||||
}
|
||||
clickHandler = new Cesium.ScreenSpaceEventHandler(sdk.viewer.canvas)
|
||||
clickHandler.setInputAction((movement) => {
|
||||
cease(sdk)
|
||||
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK)
|
||||
let viewer = sdk.viewer
|
||||
viewer.camera.cancelFlight()
|
||||
// function pauseExecution(seconds) {
|
||||
// return new Promise(resolve => setTimeout(resolve, seconds * 1000));
|
||||
// }
|
||||
closeRotateAround(sdk)
|
||||
closeViewFollow(sdk)
|
||||
viewer.camera.flyTo({
|
||||
destination: Cesium.Cartesian3.fromDegrees(points[index].position.lng, points[index].position.lat, points[index].position.alt),
|
||||
orientation: points[index].orientation,
|
||||
duration: noStart ? points[index - 1].duration : 0.5,
|
||||
maximumHeight: points[index].position.alt,
|
||||
complete: async () => {
|
||||
if (!noStart) {
|
||||
// await pauseExecution(2)
|
||||
}
|
||||
index++
|
||||
if (index <= points.length - 1) {
|
||||
executeFlyTo(sdk, points, index, true)
|
||||
}
|
||||
else if (currentRepeat && points.length > 1) {
|
||||
currentRepeat--
|
||||
executeFlyTo(sdk, points, 0)
|
||||
}
|
||||
else {
|
||||
if (clickHandler) {
|
||||
clickHandler.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
easingFunction: noStart ? Cesium.EasingFunction.LINEAR_NONE : Cesium.EasingFunction.EXPONENTIAL_OUT
|
||||
})
|
||||
}
|
||||
|
||||
const flyTo = (sdk, points = [], index = 0, noStart) => {
|
||||
currentRepeat = repeat
|
||||
executeFlyTo(sdk, points, index, noStart)
|
||||
}
|
||||
|
||||
/**设置循环次数 (Infinity: 无限循环)*/
|
||||
const setRepeat = (v) => {
|
||||
if (repeat != Number(v)) {
|
||||
repeat = Number(v)
|
||||
currentRepeat = repeat
|
||||
if (_DialogObject && _DialogObject._element && _DialogObject._element.content) {
|
||||
let repeatElm = _DialogObject._element.content.querySelector("input[name='repeat']")
|
||||
if (v === Infinity) {
|
||||
repeatElm.checked = true
|
||||
}
|
||||
else {
|
||||
repeatElm.checked = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** 停止 */
|
||||
const cease = (sdk) => {
|
||||
sdk && sdk.viewer && sdk.viewer.camera.cancelFlight()
|
||||
if (clickHandler) {
|
||||
clickHandler.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
export { open, close, flyTo, setRepeat, cease }
|
||||
235
src/Global/KeyBoard/index.js
Normal file
235
src/Global/KeyBoard/index.js
Normal file
@ -0,0 +1,235 @@
|
||||
/*
|
||||
* @Description: 使用键盘控制地图漫游
|
||||
* @Version: 1.0
|
||||
* @Author: Julian
|
||||
* @Date: 2022-04-07 16:04:07
|
||||
* @LastEditors: Julian
|
||||
* @LastEditTime: 2022-04-07 18:40:40
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @description: 使用键盘控制地图漫游初始化
|
||||
* @param {*} _viewer
|
||||
* @return {*}
|
||||
*/
|
||||
function keyboardMapRoamingInit(_viewer) {
|
||||
// 添加键盘监听事件
|
||||
document.addEventListener('keydown', keyDown.bind(_viewer), false);
|
||||
document.addEventListener('keyup', keyUp.bind(_viewer), false);
|
||||
|
||||
// 为每一帧添加监听事件
|
||||
_viewer && _viewer.clock.onTick.addEventListener(function () {
|
||||
keyboardMapRoamingRender(_viewer);
|
||||
});
|
||||
}
|
||||
|
||||
// 定义事件组
|
||||
let flags = {
|
||||
// 相机位置
|
||||
moveForward: false,
|
||||
moveBackward: false,
|
||||
moveLeft: false,
|
||||
moveRight: false,
|
||||
moveUp: false,
|
||||
moveDown: false,
|
||||
// 相机姿态
|
||||
lookUp: false,
|
||||
lookDown: false,
|
||||
lookLeft: false,
|
||||
lookRight: false,
|
||||
twistLeft: false,
|
||||
twistRight: false,
|
||||
// 缩放
|
||||
zoomIn: false,
|
||||
zoomOut: false
|
||||
}
|
||||
|
||||
|
||||
// 相机位置:W:向前;S:向后;D:向右;A:向左;Q:升高;E:降低;
|
||||
// 相机姿态:↑:抬头;↓:低头;←:左转;→:右转;0:顺时针;.:逆时针
|
||||
// 缩放:+:放大,-:缩小;
|
||||
|
||||
/**
|
||||
* @description: 根据键盘输入字符返回事件信息
|
||||
* @param {*} key
|
||||
* @return {*}
|
||||
*/
|
||||
function getFlagFromKeyboard(key) {
|
||||
switch (key) {
|
||||
// 按字符的Unicode编码
|
||||
// 相机位置
|
||||
case 87:
|
||||
return 'moveForward';
|
||||
case 83:
|
||||
return 'moveBackward';
|
||||
case 68:
|
||||
return 'moveRight';
|
||||
case 65:
|
||||
return 'moveLeft';
|
||||
case 81:
|
||||
return 'moveUp';
|
||||
case 69:
|
||||
return 'moveDown';
|
||||
// 相机姿态
|
||||
case 38:
|
||||
return 'lookUp';
|
||||
case 40:
|
||||
return 'lookDown';
|
||||
case 37:
|
||||
return 'lookLeft';
|
||||
case 39:
|
||||
return 'lookRight';
|
||||
case 96:
|
||||
return 'twistLeft';
|
||||
case 110:
|
||||
return 'twistRight';
|
||||
// 缩放
|
||||
case 107:
|
||||
return 'zoomIn';
|
||||
case 109:
|
||||
return 'zoomOut';
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 键盘按下
|
||||
* @param {*} event
|
||||
* @return {*}
|
||||
*/
|
||||
function keyDown(event) {
|
||||
let _viewer = this
|
||||
// 判断是否有输入框聚焦
|
||||
function isInputFocused() {
|
||||
const activeElement = document.activeElement;
|
||||
return (activeElement.tagName.toLowerCase() === 'input' && activeElement.type !== 'checkbox') ||
|
||||
activeElement.tagName.toLowerCase() === 'textarea' ||
|
||||
activeElement.getAttribute('role') === 'textarea';
|
||||
}
|
||||
|
||||
if (isInputFocused()) {
|
||||
// console.log('页面上有输入框已经获取焦点');
|
||||
} else if (_viewer.trackedEntity) {
|
||||
// console.log('视角跟随中');
|
||||
} else if (_viewer._firstPersonView) {
|
||||
// console.log('第一人称视角中');
|
||||
} else if (_viewer._disableKeyboardEvent) {
|
||||
// console.log('禁用键盘事件');
|
||||
} else if (event.ctrlKey && event.altKey) {
|
||||
if (event.key === 'v' || event.key === 'V') {
|
||||
let camera = _viewer.camera
|
||||
_viewer._CAMERA_SHORTCUT_VIEW = {
|
||||
orientation: { heading: camera.heading, pitch: camera.pitch, roll: camera.roll },
|
||||
position: { x: camera.position.x, y: camera.position.y, z: camera.position.z }
|
||||
}
|
||||
localStorage.setItem('CAMERA_SHORTCUT_VIEW', JSON.stringify(_viewer._CAMERA_SHORTCUT_VIEW))
|
||||
}
|
||||
if (event.key === 'f' || event.key === 'F') {
|
||||
let CAMERA_SHORTCUT_VIEW = localStorage.getItem('CAMERA_SHORTCUT_VIEW')
|
||||
_viewer._CAMERA_SHORTCUT_VIEW = JSON.parse(CAMERA_SHORTCUT_VIEW)
|
||||
if (_viewer._CAMERA_SHORTCUT_VIEW && _viewer._CAMERA_SHORTCUT_VIEW.position && _viewer._CAMERA_SHORTCUT_VIEW.orientation) {
|
||||
_viewer.camera.flyTo({
|
||||
destination: _viewer._CAMERA_SHORTCUT_VIEW.position,
|
||||
orientation: _viewer._CAMERA_SHORTCUT_VIEW.orientation
|
||||
})
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// console.log('页面上没有输入框获取焦点');
|
||||
let flagName = getFlagFromKeyboard(event.keyCode);
|
||||
if (typeof flagName !== 'undefined') {
|
||||
flags[flagName] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 键盘弹起
|
||||
* @param {*} event
|
||||
* @return {*}
|
||||
*/
|
||||
function keyUp(event) {
|
||||
let flagName = getFlagFromKeyboard(event.keyCode);
|
||||
if (typeof flagName !== 'undefined') {
|
||||
flags[flagName] = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @description: 根据事件调整相机
|
||||
* @param {*} _viewer
|
||||
* @return {*}
|
||||
*/
|
||||
function keyboardMapRoamingRender(_viewer) {
|
||||
if(!_viewer.scene.screenSpaceCameraController.enableTilt) {
|
||||
return
|
||||
}
|
||||
let camera = _viewer.camera;
|
||||
let ellipsoid = _viewer.scene.globe.ellipsoid;
|
||||
let cameraHeight = ellipsoid.cartesianToCartographic(camera.position).height;
|
||||
|
||||
// 根据相机高度设置移动距离,比默认距离移动效果更好
|
||||
let moveRate = cameraHeight / 20.0;
|
||||
let rotationRate = moveRate / 500000 / Cesium.Math.toDegrees(camera.pitch);
|
||||
|
||||
if (flags.moveForward) {
|
||||
// camera.moveForward(moveRate);
|
||||
camera.rotate(camera.right, -rotationRate);
|
||||
}
|
||||
if (flags.moveBackward) {
|
||||
// camera.moveBackward(moveRate);
|
||||
camera.rotate(camera.right, rotationRate);
|
||||
}
|
||||
if (flags.moveLeft) {
|
||||
// camera.moveLeft(moveRate);
|
||||
camera.rotate(camera.up, -rotationRate);
|
||||
}
|
||||
if (flags.moveRight) {
|
||||
// camera.moveRight(moveRate);
|
||||
camera.rotate(camera.up, rotationRate);
|
||||
}
|
||||
if (flags.moveUp) {
|
||||
camera.moveUp(moveRate);
|
||||
}
|
||||
if (flags.moveDown) {
|
||||
camera.moveDown(moveRate);
|
||||
}
|
||||
if (flags.lookUp) {
|
||||
camera.lookUp();
|
||||
}
|
||||
if (flags.lookDown) {
|
||||
camera.lookDown();
|
||||
}
|
||||
if (flags.lookLeft) {
|
||||
camera.lookLeft();
|
||||
}
|
||||
if (flags.lookRight) {
|
||||
camera.lookRight();
|
||||
}
|
||||
if (flags.twistLeft) {
|
||||
camera.twistLeft();
|
||||
}
|
||||
if (flags.twistRight) {
|
||||
camera.twistRight();
|
||||
}
|
||||
// 根据相机高度设置缩放参数
|
||||
if (flags.zoomIn) {
|
||||
let height = cameraHeight / 2
|
||||
if (height < 1) {
|
||||
height = 0
|
||||
}
|
||||
camera.zoomIn(height);
|
||||
}
|
||||
if (flags.zoomOut) {
|
||||
let height = cameraHeight / 2
|
||||
if ((cameraHeight + cameraHeight) >= 50000000) {
|
||||
height = 50000000 - cameraHeight
|
||||
}
|
||||
camera.zoomOut(height);
|
||||
}
|
||||
}
|
||||
|
||||
export { keyboardMapRoamingInit }
|
||||
117
src/Global/MapPrint/dataSource.js
Normal file
117
src/Global/MapPrint/dataSource.js
Normal file
@ -0,0 +1,117 @@
|
||||
function getTemplateData(tools) {
|
||||
return [
|
||||
{
|
||||
"name": "模板一",
|
||||
"value": "模板一",
|
||||
"id": "1",
|
||||
margin: 0.03,
|
||||
title: {
|
||||
text: '标题一',
|
||||
height: 0.05,
|
||||
bgColor: '#5d5d5d',
|
||||
color: '#ffffff',
|
||||
show: true,
|
||||
},
|
||||
border: {
|
||||
show: false,
|
||||
url: '/custom/img/map-border1.svg',
|
||||
width: 0.01,
|
||||
color: ''
|
||||
},
|
||||
plottingScale: {
|
||||
cell: 2,
|
||||
color: '#ffffff',
|
||||
show: true,
|
||||
isSelected: false,
|
||||
x: 0.87,
|
||||
y: 0.97,
|
||||
},
|
||||
data: [
|
||||
{
|
||||
text: '',
|
||||
x: 0.02,
|
||||
y: 0.93,
|
||||
isSelected: false,
|
||||
show: true,
|
||||
color: '#ffffff',
|
||||
height: 0.03
|
||||
},
|
||||
{
|
||||
text: '',
|
||||
x: 0.02,
|
||||
y: 0.97,
|
||||
isSelected: false,
|
||||
show: true,
|
||||
color: '#ffffff',
|
||||
height: 0.03
|
||||
},
|
||||
{
|
||||
x: 0.02,
|
||||
y: 0.1,
|
||||
show: false,
|
||||
isSelected: false,
|
||||
url: '/custom/img/icon-compass1.svg',
|
||||
width: 0.1,
|
||||
height: 0.1
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "模板二",
|
||||
"value": "模板二",
|
||||
"id": "2",
|
||||
margin: 0.03,
|
||||
border: {
|
||||
show: true,
|
||||
url: '/custom/img/map-border2.svg',
|
||||
width: 0.01,
|
||||
},
|
||||
title: {
|
||||
text: '标题二',
|
||||
height: 0.05,
|
||||
bgColor: '#5d5d5d',
|
||||
color: '#ffffff',
|
||||
show: true,
|
||||
},
|
||||
plottingScale: {
|
||||
cell: 2,
|
||||
color: '#ffffff',
|
||||
show: true,
|
||||
isSelected: false,
|
||||
x: 0.02,
|
||||
y: 0.97,
|
||||
},
|
||||
data: [
|
||||
{
|
||||
text: '',
|
||||
x: 0.88,
|
||||
y: 0.93,
|
||||
isSelected: false,
|
||||
show: true,
|
||||
color: '#ffffff',
|
||||
height: 0.03
|
||||
},
|
||||
{
|
||||
text: '',
|
||||
x: 0.87,
|
||||
y: 0.97,
|
||||
isSelected: false,
|
||||
show: true,
|
||||
color: '#ffffff',
|
||||
height: 0.03
|
||||
},
|
||||
{
|
||||
x: 0.91,
|
||||
y: 0.1,
|
||||
show: true,
|
||||
isSelected: false,
|
||||
url: '/custom/img/icon-compass4.svg',
|
||||
width: 0.1,
|
||||
height: 0.1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
export { getTemplateData };
|
||||
1449
src/Global/MapPrint/index.js
Normal file
1449
src/Global/MapPrint/index.js
Normal file
File diff suppressed because it is too large
Load Diff
170
src/Global/MapX/index.js
Normal file
170
src/Global/MapX/index.js
Normal file
@ -0,0 +1,170 @@
|
||||
import Tools from '../../Tools'
|
||||
import Event from '../../Event'
|
||||
|
||||
let tools
|
||||
let Xevent
|
||||
let mapx = {}
|
||||
let curRectangle = undefined;
|
||||
let centerResult = undefined
|
||||
let mouseStart = false
|
||||
let syncObject = {}
|
||||
const init = (sdk) => {
|
||||
tools = new Tools()
|
||||
let div = document.createElement('div');
|
||||
div.id = 'mapxDiv'
|
||||
div.style.width = '222px';
|
||||
div.style.height = '112px';
|
||||
div.style.position = 'absolute';
|
||||
div.style.right = '10px';
|
||||
div.style.bottom = '82px';
|
||||
div.style.zIndex = '1';
|
||||
document.getElementById(sdk.div_id).appendChild(div)
|
||||
let options = {
|
||||
imageryProvider: new Cesium.TileMapServiceImageryProvider({
|
||||
url: Cesium.buildModuleUrl("Assets/Textures/NaturalEarthII"),
|
||||
}),
|
||||
sceneMode: Cesium.SceneMode.SCENE2D,
|
||||
// mapMode2D: Cesium.MapMode2D.ROTATE,
|
||||
baseLayerPicker: false,
|
||||
geocoder: false,
|
||||
animation: false,
|
||||
fullscreenButton: false,
|
||||
navigationHelpButton: false,
|
||||
// vrButton?: boolean;
|
||||
homeButton: false,
|
||||
infoBox: false,
|
||||
sceneModePicker: false,
|
||||
selectionIndicator: false,
|
||||
timeline: false,
|
||||
shouldAnimate: true
|
||||
}
|
||||
mapx.viewer = new Cesium.Viewer('mapxDiv', options);
|
||||
mapx.viewer.camera.setView({
|
||||
destination: Cesium.Cartesian3.fromDegrees(0, 0, 40000000),
|
||||
})
|
||||
mapx.viewer.trackedEntity = undefined;
|
||||
mapx.viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(
|
||||
Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK
|
||||
);
|
||||
mapx.viewer.scene.screenSpaceCameraController.enableRotate = false;
|
||||
mapx.viewer.scene.screenSpaceCameraController.enableTranslate = false;
|
||||
mapx.viewer.scene.screenSpaceCameraController.enableZoom = false;
|
||||
mapx.viewer.scene.screenSpaceCameraController.enableTilt = false;
|
||||
mapx.viewer.scene.screenSpaceCameraController.enableLook = false;
|
||||
|
||||
// 创建范围框
|
||||
let entity = mapx.viewer.entities.add({
|
||||
name: 'mapX rectangle',
|
||||
position: new Cesium.CallbackProperty(function () {
|
||||
return (
|
||||
centerResult || Cesium.Cartesian3.fromDegrees(0, 0, 0)
|
||||
);
|
||||
}, false),
|
||||
rectangle: {
|
||||
coordinates: new Cesium.CallbackProperty(function () {
|
||||
return (
|
||||
curRectangle || Cesium.Rectangle.fromDegrees(0.0, 0.0, 0.01, 0.01)
|
||||
);
|
||||
}, false),
|
||||
material: Cesium.Color.RED.withAlpha(0.01),
|
||||
outline: true,
|
||||
outlineColor: Cesium.Color.RED,
|
||||
outlineWidth: 2,
|
||||
height: 1,
|
||||
},
|
||||
billboard: {
|
||||
image: tools.getSourceRootPath() + '/img/cross.svg',
|
||||
scale: 1,
|
||||
width: 16,
|
||||
height: 16
|
||||
},
|
||||
});
|
||||
syncObject = { sdk, entity }
|
||||
mapx.viewer.camera.percentageChanged = 0.001;
|
||||
sdk.viewer.scene.preRender.addEventListener(syncViewer, syncObject); // 鹰眼与主图同步
|
||||
let pick
|
||||
Xevent = new Event({ viewer: mapx.viewer })
|
||||
Xevent.mouse_left_down((movement, cartesian) => {
|
||||
mouseStart = true
|
||||
pick = mapx.viewer.scene.pick(movement.position)
|
||||
})
|
||||
Xevent.mouse_left_up((movement, cartesian) => {
|
||||
mouseStart = false
|
||||
})
|
||||
Xevent.mouse_move((movement, cartesian) => {
|
||||
if (pick && mouseStart) {
|
||||
let sdkCH = tools.cartesian3Towgs84(sdk.viewer.camera.position, sdk.viewer).alt
|
||||
let pos84 = tools.cartesian3Towgs84(cartesian, mapx.viewer)
|
||||
// sdk.viewer.camera.position = Cesium.Cartesian3.fromDegrees(pos84.lng, pos84.lat, sdkCH)
|
||||
sdk.viewer.camera.flyTo({
|
||||
destination: Cesium.Cartesian3.fromDegrees(pos84.lng, pos84.lat, sdkCH),
|
||||
duration: 0
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
function syncViewer() {
|
||||
if(!this.sdk || !this.sdk.viewer) {
|
||||
return
|
||||
}
|
||||
// 视角中心点(伪)
|
||||
centerResult = this.sdk.viewer.camera.pickEllipsoid(
|
||||
new Cesium.Cartesian2(
|
||||
this.sdk.viewer.canvas.clientWidth / 2,
|
||||
this.sdk.viewer.canvas.clientHeight / (2 - ((90 + this.sdk.viewer.camera.pitch / (Cesium.Math.PI / 180)) / 110)),
|
||||
),
|
||||
)
|
||||
if (!centerResult) {
|
||||
centerResult = this.sdk.viewer.camera.position
|
||||
}
|
||||
let height = tools.cartesian3Towgs84(this.sdk.viewer.camera.position, this.sdk.viewer).alt
|
||||
let centerResult84 = tools.cartesian3Towgs84(centerResult, this.sdk.viewer)
|
||||
let stepX = 120000
|
||||
let stepY = 280000
|
||||
if (height > 9000000) {
|
||||
height = 9000000
|
||||
}
|
||||
if (height < 100000) {
|
||||
this.entity.billboard.show = true
|
||||
this.entity.rectangle.show = false
|
||||
}
|
||||
else {
|
||||
this.entity.billboard.show = false
|
||||
this.entity.rectangle.show = true
|
||||
}
|
||||
curRectangle = new Cesium.Rectangle(Cesium.Math.toRadians(centerResult84.lng - (height / stepX)), Cesium.Math.toRadians(centerResult84.lat - (height / stepY)), Cesium.Math.toRadians(centerResult84.lng + (height / stepX)), Cesium.Math.toRadians(centerResult84.lat + (height / stepY)))
|
||||
};
|
||||
function open(sdk) {
|
||||
if (!mapx.viewer) {
|
||||
init(sdk)
|
||||
}
|
||||
else {
|
||||
mapx.viewer.container.style.display = 'block';
|
||||
let entity
|
||||
let entities = mapx.viewer.entities.values
|
||||
for (let i = 0; i < entities.length; i++) {
|
||||
if (entities[i].name === 'mapX rectangle') {
|
||||
entity = entities[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
sdk.viewer.scene.preRender.addEventListener(syncViewer, syncObject); // 鹰眼与主图同步
|
||||
}
|
||||
}
|
||||
function close(sdk) {
|
||||
if (!mapx.viewer) {
|
||||
return
|
||||
}
|
||||
mapx.viewer.container.style.display = 'none';
|
||||
let entity
|
||||
let entities = mapx.viewer.entities.values
|
||||
for (let i = 0; i < entities.length; i++) {
|
||||
if (entities[i].name === 'mapX rectangle') {
|
||||
entity = entities[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
sdk.viewer.scene.preRender.removeEventListener(syncViewer, syncObject)
|
||||
}
|
||||
|
||||
export { open, close }
|
||||
112
src/Global/MouseCoordinate/index.js
Normal file
112
src/Global/MouseCoordinate/index.js
Normal file
@ -0,0 +1,112 @@
|
||||
/**
|
||||
* 鼠标坐标
|
||||
*/
|
||||
import Tools from "../../Tools";
|
||||
import { getCoordinateSystem } from "../../Global/global";
|
||||
import MouseEvent from '../../Event/index'
|
||||
|
||||
let event
|
||||
let MouseCoordinateElm
|
||||
let requestAnimationFrameEventId
|
||||
|
||||
const MouseCoordinate = (sdk, status) => {
|
||||
let tools = new Tools(sdk)
|
||||
if (status) {
|
||||
if (event) {
|
||||
event.destroy()
|
||||
}
|
||||
event = new MouseEvent(sdk)
|
||||
let position = {
|
||||
x: '',
|
||||
y: '',
|
||||
z: ''
|
||||
}
|
||||
let contentElm
|
||||
if (MouseCoordinateElm) {
|
||||
contentElm = MouseCoordinateElm
|
||||
}
|
||||
else {
|
||||
contentElm = document.createElement('div');
|
||||
contentElm.style.position = 'absolute';
|
||||
contentElm.style['z-index'] = 777;
|
||||
contentElm.style.color = '#ff0000';
|
||||
contentElm.style.left = '0px';
|
||||
contentElm.style.top = '0px';
|
||||
contentElm.style.width = '100%';
|
||||
contentElm.style.height = '100%';
|
||||
contentElm.style['font-size'] = '12px';
|
||||
contentElm.style['pointer-events'] = 'none';
|
||||
contentElm.style.background = `url(${tools.getSourceRootPath()}/img/cross.png) no-repeat 100% 100%`;
|
||||
contentElm.style['background-size'] = `200% 200%`;
|
||||
MouseCoordinateElm = contentElm
|
||||
}
|
||||
sdk.viewer._element.appendChild(contentElm)
|
||||
let tmovement
|
||||
event.mouse_move((movement, cartesian) => {
|
||||
tmovement = { ...movement }
|
||||
})
|
||||
|
||||
const getPosition = () => {
|
||||
if(!tmovement) {
|
||||
return
|
||||
}
|
||||
let canvas = sdk.viewer._element.getElementsByTagName('canvas')[0]
|
||||
let left = tmovement.endPosition.x;
|
||||
let top = tmovement.endPosition.y;
|
||||
let cartesian = event.getcartesian(tmovement)
|
||||
contentElm.style['background-position-x'] = `${-canvas.width + left + 4}px`;
|
||||
contentElm.style['background-position-y'] = `${-canvas.height + top - 2}px`;
|
||||
// this.entity.position = cartesian
|
||||
if (cartesian) {
|
||||
let degrees = tools.cartesian3Towgs84(cartesian, sdk.viewer)
|
||||
let coordinateSystem = getCoordinateSystem()
|
||||
if (coordinateSystem === 'EPSG:4326') {
|
||||
position = {
|
||||
x: degrees.lng,
|
||||
y: degrees.lat,
|
||||
z: degrees.alt
|
||||
}
|
||||
contentElm.innerHTML = `<div style='width: 150px;position: absolute; z-index: 777; color: #ff0000; font-size: 12px; left:${left + 20}px; top:${top + 10}px;'><p style='margin: 0;'>经度:${degrees.lng.toFixed(6)}°</p><p style='margin: 0;'>维度:${degrees.lat.toFixed(6)}°</p><p style='margin: 0;'>海拔:${degrees.alt.toFixed(2)} m</p></div>`
|
||||
}
|
||||
else {
|
||||
let result = tools.convert([{ x: degrees.lng, y: degrees.lat, z: degrees.alt }], 'EPSG:4326', coordinateSystem)
|
||||
position = result.points[0]
|
||||
contentElm.innerHTML = `<div style='width: 150px;position: absolute; z-index: 777; color: #ff0000; font-size: 12px; left:${left + 20}px; top:${top + 10}px;'><p style='margin: 0;'>x:${position.x.toFixed(6)}</p><p style='margin: 0;'>y:${position.y.toFixed(6)}</p><p style='margin: 0;'>z:${position.z.toFixed(6)}</p></div>`
|
||||
}
|
||||
}
|
||||
else {
|
||||
let coordinateSystem = getCoordinateSystem()
|
||||
if (coordinateSystem === 'EPSG:4326') {
|
||||
contentElm.innerHTML = `<div style='width: 150px;position: absolute; z-index: 777; color: #ff0000; font-size: 12px; left:${left + 20}px; top:${top + 10}px;'><p style='margin: 0;'>经度:-</p><p style='margin: 0;'>维度:-</p><p style='margin: 0;'>海拔:-</p></div>`
|
||||
}
|
||||
else {
|
||||
contentElm.innerHTML = `<div style='width: 150px;position: absolute; z-index: 777; color: #ff0000; font-size: 12px; left:${left + 20}px; top:${top + 10}px;'><p style='margin: 0;'>x:-</p><p style='margin: 0;'>y:-</p><p style='margin: 0;'>z:-</p></div>`
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
animateUpdate()
|
||||
function animateUpdate() {
|
||||
requestAnimationFrameEventId = requestAnimationFrame(
|
||||
animateUpdate
|
||||
)
|
||||
getPosition()
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (event) {
|
||||
event.destroy()
|
||||
event = undefined
|
||||
}
|
||||
if (MouseCoordinateElm) {
|
||||
sdk.viewer._element.removeChild(MouseCoordinateElm)
|
||||
MouseCoordinateElm = undefined
|
||||
}
|
||||
if (requestAnimationFrameEventId) {
|
||||
cancelAnimationFrame(requestAnimationFrameEventId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { MouseCoordinate }
|
||||
561
src/Global/MultiViewportMode/index.js
Normal file
561
src/Global/MultiViewportMode/index.js
Normal file
@ -0,0 +1,561 @@
|
||||
/**
|
||||
* 多视口模式
|
||||
* */
|
||||
import Tools from "../../Tools";
|
||||
import MouseEvent from '../../Event'
|
||||
import { CesiumContainer } from '../global'
|
||||
import { off as offSplitScreen } from "../SplitScreen";
|
||||
import { FlwStatusSwitch, JwwStatusSwitch, getFlwStatus, getJwwStatus } from "../global"
|
||||
import { SheetIndexStatusSwitch, getStatus } from '../SheetIndex'
|
||||
|
||||
let sdk2D
|
||||
let sdk3D
|
||||
let activeViewer
|
||||
let controlViewer
|
||||
let syncObject = {}
|
||||
let handlers = []
|
||||
async function init(sdk) {
|
||||
sdk3D = sdk
|
||||
activeViewer = 0
|
||||
let tools = new Tools()
|
||||
let sdk2 = await new YJ.YJEarth(sdk.div_id)
|
||||
sdk2.viewer._element.className = 'cesium-viewer 2d'
|
||||
SheetIndexStatusSwitch(sdk2, getStatus())
|
||||
// setTimeout(() => {
|
||||
// let switchCluster = new YJ.Global.switchCluster(sdk2, true)
|
||||
// }, 500);
|
||||
CesiumContainer(sdk2, {
|
||||
compass: false, // 罗盘
|
||||
// legend: false, // 比例尺
|
||||
info: false, // 信息栏
|
||||
frame: false // 刷新率
|
||||
})
|
||||
sdk2.viewer.scene.mode = Cesium.SceneMode.SCENE2D
|
||||
sdk2D = await sdk2
|
||||
// window.sdk2D = sdk2D
|
||||
solveBug()
|
||||
syncObject = { sdks: [sdk, sdk2], tools }
|
||||
await eventBind(sdk, 0, syncObject)
|
||||
await eventBind(sdk2, 1, syncObject)
|
||||
await syncData(sdk)
|
||||
sdk.viewer.scene.preRender.addEventListener(syncViewer, syncObject)
|
||||
|
||||
sdk.viewer.imageryLayers.layerAdded.addEventListener(syncImageryLayerAdded);
|
||||
sdk.viewer.imageryLayers.layerMoved.addEventListener(syncImageryLayerMoved);
|
||||
sdk.viewer.imageryLayers.layerRemoved.addEventListener(syncImageryLayerRemoved);
|
||||
sdk.viewer.imageryLayers.layerShownOrHidden.addEventListener(syncImageryLayerShownOrHidden);
|
||||
let imageryLayers = [...sdk.viewer.imageryLayers._layers]
|
||||
imageryLayers.sort((a, b) => a._layerIndex - b._layerIndex);
|
||||
sdk2D.viewer.imageryLayers.removeAll()
|
||||
for (let i = 0; i < imageryLayers.length; i++) {
|
||||
let entity = sdk2D.viewer.imageryLayers.addImageryProvider(imageryLayers[i].imageryProvider, imageryLayers[i]._layerIndex)
|
||||
entity.show = imageryLayers[i].show
|
||||
}
|
||||
// sdk.viewer.entities.collectionChanged.addEventListener(syncEntities)
|
||||
// sdk.viewer.dataSources.dataSourceAdded.addEventListener(syncDataSources)
|
||||
|
||||
if (getFlwStatus(sdk)) {
|
||||
FlwStatusSwitch(sdk2, true)
|
||||
}
|
||||
if (getJwwStatus(sdk)) {
|
||||
JwwStatusSwitch(sdk2, true)
|
||||
}
|
||||
|
||||
}
|
||||
async function on(sdk) {
|
||||
if (sdk2D) {
|
||||
|
||||
}
|
||||
else {
|
||||
init(sdk)
|
||||
offSplitScreen()
|
||||
}
|
||||
}
|
||||
|
||||
function off(sdk) {
|
||||
sdk.viewer.scene.preRender.removeEventListener(syncViewer, syncObject)
|
||||
sdk.viewer.imageryLayers.layerAdded.removeEventListener(syncImageryLayerAdded);
|
||||
sdk.viewer.imageryLayers.layerMoved.removeEventListener(syncImageryLayerMoved);
|
||||
sdk.viewer.imageryLayers.layerRemoved.removeEventListener(syncImageryLayerRemoved);
|
||||
sdk.viewer.imageryLayers.layerShownOrHidden.removeEventListener(syncImageryLayerShownOrHidden);
|
||||
// sdk.viewer.entities.collectionChanged.removeEventListener(syncEntities)
|
||||
// sdk.viewer.dataSources.dataSourceAdded.removeEventListener(syncDataSources)
|
||||
|
||||
//primitiveAdded=undefined基元同步设置在add位置
|
||||
// sdk.viewer.scene.primitives.primitiveAdded.removeEventListener(syncPrimitivesAdded)
|
||||
for (let i = 0; i < handlers.length; i++) {
|
||||
handlers[i].destroy()
|
||||
}
|
||||
if (sdk2D) {
|
||||
sdk2D.destroy()
|
||||
handlers = []
|
||||
sdk2D = null
|
||||
sdk3D = null
|
||||
activeViewer = null
|
||||
syncObject = {}
|
||||
}
|
||||
}
|
||||
|
||||
async function syncData2(sdk, id, entityId) {
|
||||
if (sdk && sdk.viewer && sdk.viewer._element && sdk.viewer._element.className === 'cesium-viewer 2d') {
|
||||
return
|
||||
}
|
||||
if (!sdk3D || !sdk2D) {
|
||||
return
|
||||
}
|
||||
let entityMap = sdk3D.entityMap
|
||||
if (id) {
|
||||
let that = entityMap.get(id)
|
||||
if (that) {
|
||||
let that2 = sdk2D.entityMap.get(id)
|
||||
if (that2) {
|
||||
await that2.remove()
|
||||
}
|
||||
let options = syncObject.tools.deepCopyObj(that.options)
|
||||
if (that.type === 'BillboardObject') {
|
||||
options.heightReference = 1
|
||||
}
|
||||
if (that.type === 'PolygonObject') {
|
||||
options.heightMode = 0
|
||||
options.height = 0
|
||||
}
|
||||
if (!that.type || (that.type !== 'tileset' && that.type !== 'bim' && that.type !== 'glb' && that.type !== 'layer')) {
|
||||
let newObject = await new that.constructor(sdk2D, options)
|
||||
newObject.onClick = that.onClick
|
||||
newObject.onRightClick = that.onRightClick
|
||||
newObject.onMouseMove = that.onMouseMove
|
||||
if (that.type === 'TrajectoryMotion') {
|
||||
that.firstPersonView = false
|
||||
if (that.TweenAnimate) {
|
||||
let state = that.state
|
||||
if (state) {
|
||||
that.state = false
|
||||
}
|
||||
if (!newObject.state) {
|
||||
setTimeout(() => {
|
||||
newObject.setMovePositionByDistance(Number(that.TweenAnimate._object.distance.toFixed(8)) + 0.00000001)
|
||||
setTimeout(() => {
|
||||
newObject.setMovePositionByDistance(Number(that.TweenAnimate._object.distance.toFixed(8)) + 0.00000002)
|
||||
}, 500);
|
||||
}, 500);
|
||||
}
|
||||
else {
|
||||
newObject.setMovePositionByDistance(Number(that.TweenAnimate._object.distance.toFixed(8)))
|
||||
}
|
||||
that.state = state
|
||||
}
|
||||
else {
|
||||
setTimeout(() => {
|
||||
newObject.setMovePositionByDistance(0.00000001)
|
||||
setTimeout(() => {
|
||||
newObject.setMovePositionByDistance(0.00000002)
|
||||
}, 500)
|
||||
}, 500)
|
||||
}
|
||||
if (that.viewFollow) {
|
||||
newObject.viewFollow = true
|
||||
}
|
||||
}
|
||||
if (that.type === 'AttackArrowObject' || that.type === 'StraightArrowObject') {
|
||||
if (that.spreadState && that.TweenAnimate && that.TweenAnimate._object) {
|
||||
newObject.setSpreadProgressByTime(that.TweenAnimate._object.distance / that.TweenAnimate._valuesEnd.distance * that.spreadTime)
|
||||
}
|
||||
}
|
||||
if (that.type === 'PincerArrowObject') {
|
||||
if (that.spreadState && that.TweenAnimate && that.TweenAnimate._object) {
|
||||
newObject.setSpreadProgressByTime(that.TweenAnimate._object.distance1 / that.TweenAnimate._valuesEnd.distance1 * that.spreadTime)
|
||||
}
|
||||
}
|
||||
if (newObject.on && newObject.type !== 'glb') {
|
||||
if (newObject.type === 'vector') {
|
||||
newObject.data = that.data
|
||||
newObject.load(() => {
|
||||
if (newObject.entity) {
|
||||
for (let i = 0; i < newObject.entity.entities.values.length; i++) {
|
||||
newObject.entity.entities.values[i].show = that.entity.entities.values[i]._customShow === false ? false : true
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
await newObject.on()
|
||||
}
|
||||
// if (newObject.type && (newObject.type === 'tileset' || newObject.type === 'bim')) {
|
||||
// newObject.height = -10000
|
||||
// }
|
||||
// // Cesium1.98版本二维模式下初次显示有问题,1.110以上版本正常
|
||||
// if (newObject.type && (newObject.type === 'glb')) {
|
||||
// newObject.options.position.alt = 0
|
||||
// }
|
||||
}
|
||||
}
|
||||
else {
|
||||
let that2 = sdk2D.entityMap.get(id)
|
||||
if (that2) {
|
||||
await that2.remove()
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (let [key, obj] of sdk2D.entityMap) {
|
||||
let that = sdk2D.entityMap.get(key)
|
||||
if (that) {
|
||||
await that.remove()
|
||||
}
|
||||
}
|
||||
for (let [key, obj] of entityMap) {
|
||||
if (obj.type === 'BillboardObject') {
|
||||
obj.options.heightReference = 1
|
||||
}
|
||||
let options = syncObject.tools.deepCopyObj(obj.options)
|
||||
if (!obj.type || (obj.type !== 'tileset' && obj.type !== 'bim' && obj.type !== 'glb' && obj.type !== 'layer')) {
|
||||
let target = await new obj.constructor(sdk2D, options)
|
||||
target.onClick = obj.onClick
|
||||
target.onRightClick = obj.onRightClick
|
||||
target.onMouseMove = obj.onMouseMove
|
||||
if (obj.type === 'TrajectoryMotion') {
|
||||
obj.firstPersonView = false
|
||||
if (obj.TweenAnimate) {
|
||||
let state = obj.state
|
||||
if (state) {
|
||||
obj.state = false
|
||||
}
|
||||
if (!target.state) {
|
||||
setTimeout(() => {
|
||||
target.setMovePositionByDistance(Number(obj.TweenAnimate._object.distance.toFixed(8)) + 0.000000001)
|
||||
setTimeout(() => {
|
||||
target.setMovePositionByDistance(Number(obj.TweenAnimate._object.distance.toFixed(8)) + 0.000000002)
|
||||
}, 1500);
|
||||
}, 1500);
|
||||
}
|
||||
else {
|
||||
target.setMovePositionByDistance(Number(obj.TweenAnimate._object.distance.toFixed(8)))
|
||||
}
|
||||
obj.state = state
|
||||
}
|
||||
else {
|
||||
setTimeout(() => {
|
||||
target.setMovePositionByDistance(0.000000001)
|
||||
setTimeout(() => {
|
||||
target.setMovePositionByDistance(0.000000002)
|
||||
}, 1500);
|
||||
}, 1500);
|
||||
}
|
||||
if (obj.viewFollow) {
|
||||
target.viewFollow = true
|
||||
}
|
||||
// else {
|
||||
// newObject.viewFollow = false
|
||||
// }
|
||||
}
|
||||
if (obj.type === 'AttackArrowObject' || obj.type === 'StraightArrowObject') {
|
||||
if (obj.spreadState && obj.TweenAnimate && obj.TweenAnimate._object) {
|
||||
target.setSpreadProgressByTime(obj.TweenAnimate._object.distance / obj.TweenAnimate._valuesEnd.distance * obj.spreadTime)
|
||||
}
|
||||
}
|
||||
if (obj.type === 'PincerArrowObject') {
|
||||
if (obj.spreadState && obj.TweenAnimate && obj.TweenAnimate._object) {
|
||||
target.setSpreadProgressByTime(obj.TweenAnimate._object.distance1 / obj.TweenAnimate._valuesEnd.distance1 * obj.spreadTime)
|
||||
}
|
||||
}
|
||||
if (target.on && obj.type !== 'glb') {
|
||||
if (target.type === 'vector') {
|
||||
target.data = obj.data
|
||||
target.load(() => {
|
||||
if (target.entity) {
|
||||
for (let i = 0; i < target.entity.entities.values.length; i++) {
|
||||
target.entity.entities.values[i].show = obj.entity.entities.values[i]._customShow === false ? false : true
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
await target.on()
|
||||
}
|
||||
// if (obj.type && (obj.type === 'tileset' || obj.type === 'bim')) {
|
||||
// target.height = -10000
|
||||
// }
|
||||
// if (obj.type && (obj.type === 'glb')) {
|
||||
// target.options.position.alt = 0
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function syncData(sdk, id, entityId) {
|
||||
syncData2(sdk, id, entityId)
|
||||
// syncEntities()
|
||||
// syncDataSources()
|
||||
}
|
||||
|
||||
function syncEntities(entities1, entities2) {
|
||||
if (!sdk3D) {
|
||||
return
|
||||
}
|
||||
if (sdk2D) {
|
||||
if (Array.isArray(entities1) || Array.isArray(entities2)) {
|
||||
entities1 = null
|
||||
entities2 = null
|
||||
}
|
||||
if (!entities1) {
|
||||
entities1 = sdk2D.viewer.entities
|
||||
}
|
||||
if (!entities2) {
|
||||
entities2 = sdk3D.viewer.entities
|
||||
}
|
||||
let entities2D = entities1
|
||||
let entities3D = entities2
|
||||
for (let i = entities2D.values.length - 1; i >= 0; i--) {
|
||||
let flag = false
|
||||
for (let m = entities3D.values.length - 1; m >= 0; m--) {
|
||||
if (entities2D.values[i].id === entities3D.values[m].id) {
|
||||
flag = true
|
||||
entities2D.values[i] === entities3D.values[m]
|
||||
}
|
||||
}
|
||||
if (!flag) {
|
||||
entities2D.remove(entities2D.values[i])
|
||||
}
|
||||
}
|
||||
for (let m = entities3D.values.length - 1; m >= 0; m--) {
|
||||
let flag = false
|
||||
for (let i = entities2D.values.length - 1; i >= 0; i--) {
|
||||
if (entities2D.values[i].id === entities3D.values[m].id) {
|
||||
flag = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!flag) {
|
||||
let entity = entities2D.add(entities3D.values[m])
|
||||
// if (entity.rectangle) {
|
||||
// // 设置高度,否则在某些位置无法显示,但色彩会变暗
|
||||
// entity.rectangle.height = 0
|
||||
// console.log('242342354235',entities3D.values[m])
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function syncDataSources(dataSources, type) {
|
||||
if (!sdk3D) {
|
||||
return
|
||||
}
|
||||
if (sdk2D) {
|
||||
let dataSources2D = sdk2D.viewer.dataSources
|
||||
if (dataSources) {
|
||||
for (let i = dataSources2D._dataSources.length - 1; i >= 0; i--) {
|
||||
if (dataSources2D._dataSources[i].name === dataSources.name) {
|
||||
if (type === 'entities') {
|
||||
syncEntities(dataSources2D._dataSources[i].entities, dataSources.entities)
|
||||
}
|
||||
if (type === 'clustering') {
|
||||
dataSources2D._dataSources[i].clustering.enabled = dataSources.clustering.enabled
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// for (let m = dataSources3D._dataSources.length - 1; m >= 0; m--) {
|
||||
// let flag = false
|
||||
// for (let i = dataSources2D._dataSources.length - 1; i >= 0; i--) {
|
||||
// console.log(dataSources2D._dataSources[i].name, dataSources3D._dataSources[m].name)
|
||||
// if (dataSources2D._dataSources[i].name === dataSources3D._dataSources[m].name) {
|
||||
// flag = true
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
// if (!flag) {
|
||||
// dataSources2D.add(dataSources3D._dataSources[m])
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
function syncImageryLayerAdded(layer, index) {
|
||||
sdk2D.viewer.imageryLayers.addImageryProvider(layer.imageryProvider, index)
|
||||
}
|
||||
function syncImageryLayerMoved(layer, newindxe, oldindex) {
|
||||
let layer2d = sdk2D.viewer.imageryLayers._layers[oldindex]
|
||||
if (!layer2d) {
|
||||
return
|
||||
}
|
||||
// 移到最底层
|
||||
if (newindxe === 0) {
|
||||
sdk2D.viewer.imageryLayers.lowerToBottom(layer2d)
|
||||
}
|
||||
// 移到最高层
|
||||
else if (newindxe === sdk3D.viewer.imageryLayers._layers.length - 1) {
|
||||
sdk2D.viewer.imageryLayers.raiseToTop(layer2d)
|
||||
}
|
||||
else {
|
||||
if (newindxe < oldindex) {
|
||||
sdk2D.viewer.imageryLayers.lower(layer2d)
|
||||
}
|
||||
else {
|
||||
sdk2D.viewer.imageryLayers.raise(layer2d)
|
||||
}
|
||||
}
|
||||
}
|
||||
function syncImageryLayerRemoved(layer, index) {
|
||||
let layer2d = sdk2D.viewer.imageryLayers._layers[index]
|
||||
if (!layer2d) {
|
||||
return
|
||||
}
|
||||
sdk2D.viewer.imageryLayers.remove(layer2d)
|
||||
}
|
||||
function syncImageryLayerShownOrHidden(layer, index, state) {
|
||||
let layer2d = sdk2D.viewer.imageryLayers._layers[index]
|
||||
if (!layer2d) {
|
||||
return
|
||||
}
|
||||
layer2d.show = state
|
||||
}
|
||||
|
||||
async function syncPrimitives(primitive) {
|
||||
if (!sdk3D) {
|
||||
return
|
||||
}
|
||||
if (sdk2D) {
|
||||
// await sdk2D.viewer.scene.primitives.remove(primitive)
|
||||
// await sdk2D.viewer.scene.primitives.add(primitive)
|
||||
let primitives2D = sdk2D.viewer.scene.primitives._primitives
|
||||
let primitives3D = sdk3D.viewer.scene.primitives._primitives
|
||||
// console.log(primitives2D, primitives3D)
|
||||
// setTimeout(() => {
|
||||
// sdk2D.viewer.scene.primitives._primitives[1] = sdk3D.viewer.scene.primitives._primitives[1]
|
||||
// }, 2000);
|
||||
for (let i = primitives2D.length - 1; i >= 1; i--) {
|
||||
let flag = false
|
||||
for (let m = primitives3D.length - 1; m >= 1; m--) {
|
||||
if (primitives3D[m].id && primitives2D[m].id && (primitives3D[m].id === primitives2D[i].id)) {
|
||||
flag = true
|
||||
}
|
||||
}
|
||||
if (!flag) {
|
||||
sdk2D.viewer.scene.primitives.remove(primitives2D[i])
|
||||
}
|
||||
}
|
||||
for (let m = primitives3D.length - 1; m >= 1; m--) {
|
||||
let flag = false
|
||||
for (let i = primitives2D.length - 1; i >= 1; i--) {
|
||||
if (primitives3D[m].id && primitives2D[m].id && (primitives3D[m].id === primitives2D[i].id)) {
|
||||
flag = true
|
||||
primitives2D[i].show = primitives3D[m].show
|
||||
primitives2D[i].startColor = primitives3D[m].startColor
|
||||
primitives2D[i].endColor = primitives3D[m].endColor
|
||||
primitives2D[i].minimumSpeed = primitives3D[m].minimumSpeed
|
||||
primitives2D[i].maximumSpeed = primitives3D[m].maximumSpeed
|
||||
primitives2D[i].minimumParticleLife = primitives3D[m].minimumParticleLife
|
||||
primitives2D[i].maximumParticleLife = primitives3D[m].maximumParticleLife
|
||||
primitives2D[i].startScale = primitives3D[m].startScale
|
||||
primitives2D[i].endScale = primitives3D[m].endScale
|
||||
primitives2D[i].emissionRate = primitives3D[m].emissionRate
|
||||
primitives2D[i].particleSize = primitives3D[m].particleSize
|
||||
primitives2D[i].modelMatrix = primitives3D[m].modelMatrix
|
||||
}
|
||||
}
|
||||
if (!flag) {
|
||||
sdk2D.viewer.scene.primitives.add(primitives3D[m])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function eventBind(sdk, i, syncObject) {
|
||||
let handler = new Cesium.ScreenSpaceEventHandler(
|
||||
sdk.viewer.canvas
|
||||
)
|
||||
handler.setInputAction(() => {
|
||||
activeViewer = i
|
||||
}, Cesium.ScreenSpaceEventType.LEFT_DOWN)
|
||||
handler.setInputAction(() => {
|
||||
activeViewer = i
|
||||
}, Cesium.ScreenSpaceEventType.RIGHT_DOWN)
|
||||
handler.setInputAction(() => {
|
||||
activeViewer = i
|
||||
}, Cesium.ScreenSpaceEventType.WHEEL)
|
||||
handlers.push(handler)
|
||||
}
|
||||
|
||||
function syncViewer() {
|
||||
let sdk = this.sdks[activeViewer]
|
||||
let sdk2
|
||||
|
||||
if (activeViewer === 0) {
|
||||
sdk2 = this.sdks[1]
|
||||
}
|
||||
else if (activeViewer === 1) {
|
||||
sdk2 = this.sdks[0]
|
||||
}
|
||||
// this.sdks[0].viewer.trackedEntity = null
|
||||
// this.sdks[1].viewer.trackedEntity = null
|
||||
if (sdk.viewer.scene.mode === 2) {
|
||||
if (this.sdks[0].viewer.trackedEntity) {
|
||||
let distance = sdk.viewer.camera.positionCartographic.height
|
||||
sdk2.viewer.camera.lookAt(
|
||||
Cesium.Cartesian3.fromRadians(sdk.viewer.camera.positionCartographic.longitude, sdk.viewer.camera.positionCartographic.latitude, 0),
|
||||
new Cesium.HeadingPitchRange(0, Cesium.Math.toRadians(-90), distance)
|
||||
)
|
||||
}
|
||||
else {
|
||||
if (this.sdks[1].viewer.trackedEntity) {
|
||||
this.sdks[1].viewer.entities.remove(this.sdks[1].viewer.trackedEntity)
|
||||
this.sdks[1].viewer.trackedEntity = null
|
||||
}
|
||||
let centerResult84 = this.tools.cartesian3Towgs84(Cesium.Cartesian3.fromRadians(sdk.viewer.camera.positionCartographic.longitude, sdk.viewer.camera.positionCartographic.latitude, sdk.viewer.camera.positionCartographic.height), sdk.viewer)
|
||||
sdk2.viewer.camera.setView({
|
||||
destination: Cesium.Cartesian3.fromDegrees(centerResult84.lng, centerResult84.lat, centerResult84.alt),
|
||||
})
|
||||
}
|
||||
}
|
||||
else {
|
||||
// 视角中心点(伪)
|
||||
let centerResult = sdk.viewer.camera.pickEllipsoid(
|
||||
new Cesium.Cartesian2(
|
||||
sdk.viewer.canvas.clientWidth / 2,
|
||||
sdk.viewer.canvas.clientHeight / (2 - ((90 + sdk.viewer.camera.pitch / (Cesium.Math.PI / 180)) / 110)),
|
||||
),
|
||||
)
|
||||
if (!centerResult) {
|
||||
centerResult = sdk.viewer.camera.positionWC
|
||||
}
|
||||
|
||||
let height = this.tools.cartesian3Towgs84(sdk.viewer.camera.positionWC, sdk.viewer).alt
|
||||
let centerResult84 = this.tools.cartesian3Towgs84(centerResult, sdk.viewer)
|
||||
|
||||
// console.log('--------------', sdk.viewer.camera.position, sdk.viewer.camera.positionWC, centerResult84, height)
|
||||
|
||||
sdk2.viewer.camera.setView({
|
||||
destination: Cesium.Cartesian3.fromDegrees(centerResult84.lng, centerResult84.lat, height),
|
||||
// orientation: {
|
||||
// heading: sdk2.viewer.camera.heading,
|
||||
// pitch: sdk2.viewer.camera.pitch,
|
||||
// roll: sdk2.viewer.camera.roll
|
||||
// }
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
function get2DView() {
|
||||
return sdk2D
|
||||
}
|
||||
|
||||
function get3DView() {
|
||||
return sdk3D
|
||||
}
|
||||
|
||||
function solveBug() {
|
||||
// 在能显示的地方加载一个多边形,解决二维模式下某些地方无法显示多边形的bug,原因不明
|
||||
sdk2D && sdk2D.viewer.entities.add({
|
||||
show: false,
|
||||
polygon: {
|
||||
hierarchy: new Cesium.PolygonHierarchy(Cesium.Cartesian3.fromDegreesArray([100, 50, 100.0001, 50, 100.0001, 50.0001]))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function setActiveViewer(v) {
|
||||
activeViewer = v
|
||||
}
|
||||
|
||||
|
||||
export { on, off, syncData, syncEntities, syncDataSources, syncPrimitives, get2DView, get3DView, setActiveViewer }
|
||||
92
src/Global/ScreenRecord/index.js
Normal file
92
src/Global/ScreenRecord/index.js
Normal file
@ -0,0 +1,92 @@
|
||||
class ScreenRecord {
|
||||
constructor() {
|
||||
this.start()
|
||||
}
|
||||
|
||||
start() {
|
||||
navigator.mediaDevices.getDisplayMedia({
|
||||
video: true
|
||||
})
|
||||
.then((stream) => {
|
||||
// 需要更好的浏览器支持
|
||||
// const mime = MediaRecorder.isTypeSupported('video/webm; codecs=vp9')
|
||||
// ? 'video/webm; codecs=vp9'
|
||||
// : 'video/webm'
|
||||
this.mediaRecorder = new MediaRecorder(stream, {
|
||||
// mimeType: mime,
|
||||
mimeType: 'video/webm',
|
||||
})
|
||||
|
||||
let chunks = []
|
||||
this.mediaRecorder.addEventListener('dataavailable', function (e) {
|
||||
chunks.push(e.data)
|
||||
})
|
||||
|
||||
this.mediaRecorder.addEventListener('stop', async () => {
|
||||
try {
|
||||
let blob = new Blob(chunks, {
|
||||
type: 'video/mp4',
|
||||
})
|
||||
const opts = {
|
||||
suggestedName: '视频录制.mp4',
|
||||
types: [
|
||||
{
|
||||
description: '文件类型',
|
||||
accept: {
|
||||
'video/mp4': ['.mp4'],
|
||||
}
|
||||
}
|
||||
],
|
||||
excludeAcceptAllOption: true
|
||||
};
|
||||
|
||||
const handle = await window.showSaveFilePicker(opts); // 打开保存文件对话框
|
||||
const writable = await handle.createWritable(); // 创建可写入的文件对象
|
||||
// 写入视频内容
|
||||
writable.write(blob);
|
||||
await writable.close();
|
||||
YJ.Global.ScreenRecord.screenRecord = null
|
||||
} catch (error) {
|
||||
console.info('文件保存失败:', error);
|
||||
}
|
||||
|
||||
// let blob = new Blob(chunks, {
|
||||
// type: chunks[0].type,
|
||||
// })
|
||||
// let url = URL.createObjectURL(blob)
|
||||
|
||||
// let a = document.createElement('a')
|
||||
// a.href = url
|
||||
// a.download = 'video.webm'
|
||||
// a.click()
|
||||
// this.recording = false
|
||||
// YJ.Global.ScreenRecord.screenRecord = null
|
||||
})
|
||||
|
||||
// 必须手动启动
|
||||
this.mediaRecorder.start()
|
||||
})
|
||||
.catch((e) => {
|
||||
console.info('取消录屏')
|
||||
console.info(e)
|
||||
YJ.Global.ScreenRecord.screenRecord = null
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function startScreenRecord() {
|
||||
if (YJ.Global.ScreenRecord.screenRecord) {
|
||||
return '录屏任务进行中'
|
||||
} else {
|
||||
YJ.Global.ScreenRecord.screenRecord = new ScreenRecord()
|
||||
}
|
||||
}
|
||||
|
||||
function stopScreenRecord() {
|
||||
if (YJ.Global.ScreenRecord && YJ.Global.ScreenRecord.screenRecord && YJ.Global.ScreenRecord.screenRecord) {
|
||||
YJ.Global.ScreenRecord.screenRecord.mediaRecorder.stop()
|
||||
YJ.Global.ScreenRecord.screenRecord = null
|
||||
}
|
||||
}
|
||||
|
||||
export { startScreenRecord, stopScreenRecord }
|
||||
707
src/Global/ScreenShot/index.js
Normal file
707
src/Global/ScreenShot/index.js
Normal file
@ -0,0 +1,707 @@
|
||||
import Tools from '../../Tools'
|
||||
import Dialog from '../../Obj/Element/Dialog';
|
||||
import { legp } from '../../Obj/Element/datalist';
|
||||
import MapPrint from '../MapPrint';
|
||||
import { off as offSplitScreen } from "../SplitScreen";
|
||||
import { off as offMultiViewportMode } from "../MultiViewportMode";
|
||||
|
||||
// 生成快照
|
||||
const convertToImage = (container, options = {}) => {
|
||||
// 设置放大倍数
|
||||
const scale = window.devicePixelRatio;
|
||||
|
||||
// 传入节点原始宽高
|
||||
const width = container.offsetWidth;
|
||||
const height = container.offsetHeight;
|
||||
|
||||
// html2canvas配置项
|
||||
const ops = {
|
||||
scale,//比例,越大分辨率越高,图片越小
|
||||
width,
|
||||
height,
|
||||
async: false,
|
||||
x: 0,
|
||||
y: 0,
|
||||
backgroundColor: 'rgb(20,47,65)',
|
||||
imageTimeout: 0,
|
||||
useCORS: true,//允许跨域
|
||||
allowTaint: false, //允许跨域数据污染'被污染'的canvas
|
||||
tainttest: true,
|
||||
foreignObjectRendering: true, //在浏览器支持的情况下使用ForeignObject模式渲染图片
|
||||
...options
|
||||
};
|
||||
|
||||
return html2canvas(container, ops).then(canvas => {
|
||||
// 返回图片的二进制数据
|
||||
return canvas.toDataURL("image/png");
|
||||
});
|
||||
}
|
||||
|
||||
async function ScreenShot(sdk, cd = () => { }) {
|
||||
// const imgBlobData = await convertToImage(sdk.viewer.canvas);
|
||||
const imgBlobData = sdk.viewer.canvas.toDataURL()
|
||||
cd && cd(imgBlobData)
|
||||
// try {
|
||||
// const imgBlobData = await convertToImage(sdk.viewer.canvas);
|
||||
// let arr = imgBlobData.split(','), mime = arr[0].match(/:(.*?);/)[1],
|
||||
// bstr = atob(arr[1]), i = bstr.length, u8arr = new Uint8Array(i);
|
||||
// while (i--) {
|
||||
// u8arr[i] = bstr.charCodeAt(i);
|
||||
// }
|
||||
|
||||
// let blob = new Blob([u8arr], { type: mime });
|
||||
// const opts = {
|
||||
// suggestedName: '截图.png',
|
||||
// types: [
|
||||
// {
|
||||
// description: '文件类型',
|
||||
// accept: {
|
||||
// 'image/png': ['.png'],
|
||||
// 'image/jpg': ['.jpg']
|
||||
// }
|
||||
// }
|
||||
// ],
|
||||
// excludeAcceptAllOption: true
|
||||
// };
|
||||
|
||||
// const handle = await window.showSaveFilePicker(opts); // 打开保存文件对话框
|
||||
// const writable = await handle.createWritable(); // 创建可写入的文件对象
|
||||
// // 写入视频内容
|
||||
// writable.write(blob);
|
||||
// await writable.close();
|
||||
// YJ.Global.ScreenRecord.screenRecord = null
|
||||
// } catch (error) {
|
||||
// console.info('文件保存失败:', error);
|
||||
// }
|
||||
}
|
||||
|
||||
let _DialogObject
|
||||
|
||||
async function ScreenShotHD(sdk, options = {}, cd = () => { }) {
|
||||
if (!sdk) {
|
||||
return
|
||||
}
|
||||
offSplitScreen(sdk)
|
||||
offMultiViewportMode(sdk)
|
||||
if (_DialogObject) {
|
||||
_DialogObject.close()
|
||||
_DialogObject = null
|
||||
}
|
||||
|
||||
let enableTranslate = sdk.viewer.scene.screenSpaceCameraController.enableTranslate
|
||||
let enableTilt = sdk.viewer.scene.screenSpaceCameraController.enableTilt
|
||||
let enableLook = sdk.viewer.scene.screenSpaceCameraController.enableLook
|
||||
|
||||
let scale = 1
|
||||
let level
|
||||
|
||||
let progressInputElm
|
||||
let progressBarElm
|
||||
let rangeNodeActive
|
||||
let rangeNodeActiveText
|
||||
let startScreenShotObject
|
||||
let tools = new Tools();
|
||||
_DialogObject = await new Dialog(sdk, {}, {
|
||||
title: '高清出图', left: '180px', top: '100px',
|
||||
confirmCallBack: (options) => {
|
||||
if (startScreenShotObject) {
|
||||
startScreenShotObject.desist()
|
||||
startScreenShotObject = null
|
||||
}
|
||||
progressInputElm && (progressInputElm.style.width = '0%')
|
||||
rangeNodeActive && (rangeNodeActive.style.left = '0%')
|
||||
progressBarElm && (progressBarElm.style.width = '0%')
|
||||
rangeNodeActiveText && (rangeNodeActiveText.innerHTML = '0%')
|
||||
startScreenShotObject = new startScreenShot()
|
||||
},
|
||||
closeCallBack: () => {
|
||||
sdk.viewer.scene.screenSpaceCameraController.enableTranslate = enableTranslate;
|
||||
sdk.viewer.scene.screenSpaceCameraController.enableTilt = enableTilt;
|
||||
sdk.viewer.scene.screenSpaceCameraController.enableLook = enableLook;
|
||||
sdk.viewer._element.getElementsByClassName('compass')[0].style.pointerEvents = 'auto'
|
||||
if (startScreenShotObject) {
|
||||
startScreenShotObject.desist()
|
||||
startScreenShotObject = null
|
||||
}
|
||||
_DialogObject = undefined
|
||||
}
|
||||
})
|
||||
_DialogObject._element.body.className = _DialogObject._element.body.className + ' screenShotHD'
|
||||
let contentElm = document.createElement('div');
|
||||
contentElm.innerHTML = `
|
||||
<span class="custom-divider"></span>
|
||||
<div class="div-item">
|
||||
<div class="row text" style="align-items: flex-start;">
|
||||
<div class="col">
|
||||
<span>当前窗口长宽:<span class="input-width">${sdk.viewer.canvas.width}</span>*<span class="input-height">${sdk.viewer.canvas.height}</span>像素</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row scale-box" style="align-items: flex-start;">
|
||||
<div class="col">
|
||||
<span class="label">图片大小</span>
|
||||
<div class="input input-select scale"></div>
|
||||
<span>倍窗口</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row text" style="align-items: flex-start;">
|
||||
<div class="col">
|
||||
<span>输出图片长宽:<span class="output-width">${sdk.viewer.canvas.width * scale}</span>*<span class="output-height">${sdk.viewer.canvas.height * scale}</span>像素</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" style="align-items: flex-start; margin-bottom: 20px;">
|
||||
<div class="col">
|
||||
<span class="label">输出进度</span>
|
||||
<div class="range-box">
|
||||
<div class="range-bg">
|
||||
<div class="range-process-box">
|
||||
<div class="range-process"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="range-node-box">
|
||||
<span class="range-node-text">0%</span>
|
||||
<span class="range-node-text">100%</span>
|
||||
<div class="range-node-active"><span class="range-node-active-text">0%</span></div>
|
||||
</div>
|
||||
<input class="progress-input" type="range" max="100" min="0" step="0.01">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="custom-divider"></span>
|
||||
`
|
||||
_DialogObject.contentAppChild(contentElm)
|
||||
|
||||
sdk.viewer.scene.screenSpaceCameraController.enableTranslate = false;
|
||||
sdk.viewer.scene.screenSpaceCameraController.enableTilt = false;
|
||||
sdk.viewer.scene.screenSpaceCameraController.enableLook = false;
|
||||
sdk.viewer._element.getElementsByClassName('compass')[0].style.pointerEvents = 'none'
|
||||
|
||||
|
||||
let centerResult = sdk.viewer.camera.pickEllipsoid(
|
||||
new Cesium.Cartesian2(
|
||||
sdk.viewer.canvas.clientWidth / 2,
|
||||
sdk.viewer.canvas.clientHeight / 2,
|
||||
),
|
||||
)
|
||||
if (!centerResult) {
|
||||
centerResult = sdk.viewer.camera.pickEllipsoid(
|
||||
new Cesium.Cartesian2(
|
||||
sdk.viewer.canvas.clientWidth / 2,
|
||||
sdk.viewer.canvas.clientHeight / (2 - ((90 + sdk.viewer.camera.pitch / (Cesium.Math.PI / 180)) / 110)),
|
||||
),
|
||||
)
|
||||
if (!centerResult) {
|
||||
centerResult = sdk.viewer.camera.position
|
||||
}
|
||||
}
|
||||
let height = tools.cartesian3Towgs84(sdk.viewer.camera.position, sdk.viewer).alt
|
||||
let centerResult84 = tools.cartesian3Towgs84(centerResult, sdk.viewer)
|
||||
sdk.viewer.camera.flyTo({
|
||||
destination: Cesium.Cartesian3.fromDegrees(centerResult84.lng, centerResult84.lat, height),
|
||||
orientation: { heading: 0, pitch: Cesium.Math.toRadians(-90), roll: 0 },
|
||||
duration: 1,
|
||||
})
|
||||
|
||||
|
||||
let scaleData = []
|
||||
for (let i = 1; i <= 10; i++) {
|
||||
scaleData.push({
|
||||
name: i,
|
||||
value: i
|
||||
})
|
||||
}
|
||||
progressInputElm = document.getElementsByClassName('progress-input')[0]
|
||||
progressBarElm = document.getElementsByClassName('range-process')[0]
|
||||
rangeNodeActive = contentElm.getElementsByClassName('range-node-active')[0]
|
||||
rangeNodeActiveText = contentElm.getElementsByClassName('range-node-active-text')[0]
|
||||
let scaleDataLegpObject = legp(_DialogObject._element.content.getElementsByClassName('scale-box')[0], ".scale")
|
||||
if (scaleDataLegpObject) {
|
||||
scaleDataLegpObject.legp_search(scaleData)
|
||||
let scaleDataLegpElm = _DialogObject._element.content.getElementsByClassName('scale')[0].getElementsByTagName('input')[0]
|
||||
scale = scaleData[0].value
|
||||
scaleDataLegpObject.legp_searchActive(scaleData[0].value)
|
||||
scaleDataLegpElm.value = scaleData[0].value
|
||||
scaleDataLegpElm.addEventListener('input', () => {
|
||||
for (let i = 0; i < scaleData.length; i++) {
|
||||
if (scaleData[i].value == scaleDataLegpElm.value) {
|
||||
scale = scaleData[i].value
|
||||
_DialogObject._element.content.getElementsByClassName('output-width')[0].innerHTML = sdk.viewer.canvas.width * scale
|
||||
_DialogObject._element.content.getElementsByClassName('output-height')[0].innerHTML = sdk.viewer.canvas.height * scale
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
class startScreenShot {
|
||||
constructor() {
|
||||
this.state = false
|
||||
this.start()
|
||||
}
|
||||
start() {
|
||||
if (sdk.viewer.scene.imageryLayers._layers.length <= 1) {
|
||||
this.error = '未加载底图!'
|
||||
window.ELEMENT && window.ELEMENT.Message({
|
||||
message: this.error,
|
||||
type: 'warning',
|
||||
duration: 1500
|
||||
});
|
||||
console.warn(this.error)
|
||||
return
|
||||
}
|
||||
let haveBaseMap = false
|
||||
for (let i = 0; i < sdk.viewer.scene.imageryLayers._layers.length; i++) {
|
||||
let layer = sdk.viewer.scene.imageryLayers._layers[i];
|
||||
if (layer && layer.show && (!layer.notes || layer.notes !== 'default-base-map')) {
|
||||
haveBaseMap = true
|
||||
}
|
||||
}
|
||||
if (!haveBaseMap) {
|
||||
this.error = '未加载底图!'
|
||||
window.ELEMENT && window.ELEMENT.Message({
|
||||
message: this.error,
|
||||
type: 'warning',
|
||||
duration: 1500
|
||||
});
|
||||
console.warn(this.error)
|
||||
return
|
||||
}
|
||||
let scaleZoom = 0;
|
||||
this.state = true;
|
||||
let _this = this
|
||||
computeLayers(1);
|
||||
|
||||
function computeLayers(s) {
|
||||
let num = s * 2;
|
||||
if (num <= scale) {
|
||||
scaleZoom++;
|
||||
computeLayers(num);
|
||||
}
|
||||
}
|
||||
scaleZoom = scaleZoom + 1;
|
||||
let centerResult = sdk.viewer.camera.pickEllipsoid(
|
||||
new Cesium.Cartesian2(
|
||||
sdk.viewer.canvas.width / 2,
|
||||
sdk.viewer.canvas.height / (2 - ((90 + sdk.viewer.camera.pitch / (Cesium.Math.PI / 180)) / 110))
|
||||
)
|
||||
);
|
||||
if (!centerResult) {
|
||||
centerResult = sdk.viewer.camera.position;
|
||||
}
|
||||
function altitudeToZoom(altitude) {
|
||||
let A = 40487.57;
|
||||
let B = 0.00007096758;
|
||||
let C = 91610.74;
|
||||
let D = -40467.74;
|
||||
return Math.round(D + (A - D) / (1 + Math.pow(altitude / C, B)));
|
||||
}
|
||||
let height = tools.cartesian3Towgs84(sdk.viewer.camera.position, sdk.viewer).alt;
|
||||
let zoom = altitudeToZoom(height) + 1;
|
||||
|
||||
let rectangle = sdk.viewer.camera.computeViewRectangle();
|
||||
// if (height > 9000000) {
|
||||
// height = 9000000
|
||||
// }
|
||||
// let curRectangle = new Cesium.Rectangle(Cesium.Math.toRadians(centerResult84.lng - (height / stepX)), Cesium.Math.toRadians(centerResult84.lat - (height / stepY)), Cesium.Math.toRadians(centerResult84.lng + (height / stepX)), Cesium.Math.toRadians(centerResult84.lat + (height / stepY)))
|
||||
// for (let i = 1; i < sdk.viewer.scene.imageryLayers._layers.length; i++) {
|
||||
// let layer = sdk.viewer.scene.imageryLayers._layers[i]
|
||||
// createCanvas(layer)
|
||||
// }
|
||||
let total;
|
||||
let totalCount = 0;
|
||||
let progress = {};
|
||||
let index = 0;
|
||||
let layerLength = 0
|
||||
let countIndex = 0
|
||||
for (let i = 0; i < sdk.viewer.scene.imageryLayers._layers.length; i++) {
|
||||
let layer = sdk.viewer.scene.imageryLayers._layers[i];
|
||||
if (layer && layer.show && layer.imageryProvider && layer.imageryProvider.url && Cesium.Rectangle.intersection(rectangle, layer.imageryProvider.rectangle) && (!layer.notes || layer.notes !== 'default-base-map')) {
|
||||
layerLength++
|
||||
}
|
||||
}
|
||||
let itemTotalProgress = 100 / layerLength
|
||||
let flag = false
|
||||
createCanvas(index);
|
||||
function createCanvas(i, totalCanvas) {
|
||||
let layer = sdk.viewer.scene.imageryLayers._layers[i];
|
||||
if (!layer) {
|
||||
if (!flag) {
|
||||
_this.error = '当前范围内未找到底图数据!'
|
||||
window.ELEMENT && window.ELEMENT.Message({
|
||||
message: _this.error,
|
||||
type: 'warning',
|
||||
duration: 1500
|
||||
});
|
||||
console.warn(_this.error)
|
||||
}
|
||||
return
|
||||
}
|
||||
if (!layer.show || !layer.imageryProvider || !layer.imageryProvider.url || !Cesium.Rectangle.intersection(rectangle, layer.imageryProvider.rectangle) || (layer.notes && layer.notes === 'default-base-map')) {
|
||||
let m = i += 1;
|
||||
createCanvas(m, totalCanvas);
|
||||
return;
|
||||
}
|
||||
flag = true
|
||||
countIndex++
|
||||
progress[i] = {
|
||||
value: 0
|
||||
}
|
||||
let itemTotalCount = 0;
|
||||
let targetLevel
|
||||
let imageryProvider = layer.imageryProvider;
|
||||
if (level || level === 0) {
|
||||
targetLevel = level
|
||||
}
|
||||
else {
|
||||
targetLevel = (zoom + scaleZoom - 1)
|
||||
if (targetLevel > imageryProvider.maximumLevel) {
|
||||
targetLevel = imageryProvider.maximumLevel
|
||||
}
|
||||
if (targetLevel < imageryProvider.minimumLevel) {
|
||||
targetLevel = imageryProvider.minimumLevel
|
||||
}
|
||||
}
|
||||
function readyPromise() {
|
||||
let MinTile = imageryProvider.tilingScheme.positionToTileXY(
|
||||
Cesium.Rectangle.northwest(rectangle),
|
||||
targetLevel
|
||||
);
|
||||
let MaxTile = imageryProvider.tilingScheme.positionToTileXY(
|
||||
Cesium.Rectangle.southeast(rectangle),
|
||||
targetLevel
|
||||
);
|
||||
if (!MinTile || !MaxTile) {
|
||||
let error = '超出地球范围!'
|
||||
window.ELEMENT && window.ELEMENT.Message({
|
||||
message: error,
|
||||
type: 'warning',
|
||||
duration: 1500
|
||||
});
|
||||
console.warn(error)
|
||||
return
|
||||
}
|
||||
let OfXTilesAtLevel = imageryProvider.tilingScheme.getNumberOfXTilesAtLevel(targetLevel)
|
||||
let OfYTilesAtLevel = imageryProvider.tilingScheme.getNumberOfYTilesAtLevel(targetLevel)
|
||||
let MinTileX = MinTile.x;
|
||||
let MinTileY = MinTile.y;
|
||||
let MaxTileX = MaxTile.x;
|
||||
let MaxTileY = MaxTile.y;
|
||||
|
||||
// if (MinTileX > MaxTileX) {
|
||||
// MinTileX = MinTileX - OfXTilesAtLevel
|
||||
// }
|
||||
|
||||
let imgWidth = 256;
|
||||
let imgHeight = 256;
|
||||
|
||||
let itemTotal = (MaxTileX - MinTileX + 1) * (MaxTileY - MinTileY + 1);
|
||||
// var canvas = new fabric.Canvas();
|
||||
let canvas = document.createElement('canvas');
|
||||
canvas.width = (MaxTileX - MinTileX + 1) * imgWidth;
|
||||
canvas.height = (MaxTileY - MinTileY + 1) * imgHeight;
|
||||
let ctx = canvas.getContext('2d');
|
||||
let maxRectangle = imageryProvider.tilingScheme.tileXYToRectangle(MaxTileX, MaxTileY, targetLevel);
|
||||
let minRectangle = imageryProvider.tilingScheme.tileXYToRectangle(MinTileX, MinTileY, targetLevel);
|
||||
let canvasNativeRectangle = new Cesium.Rectangle(minRectangle.west, maxRectangle.south, maxRectangle.east, minRectangle.north);
|
||||
// sdk.viewer.entities.add({
|
||||
// rectangle: {
|
||||
// coordinates: canvasNativeRectangle,
|
||||
// material: Cesium.Color.YELLOW.withAlpha(0.2),
|
||||
// },
|
||||
// });
|
||||
// sdk.viewer.entities.add({
|
||||
// rectangle: {
|
||||
// coordinates: rectangle,
|
||||
// material: Cesium.Color.BLACK.withAlpha(0.2),
|
||||
// },
|
||||
// });
|
||||
let nativeRectangle = rectangle;
|
||||
let x1 = nativeRectangle.west - canvasNativeRectangle.west;
|
||||
let x2 = canvasNativeRectangle.east - nativeRectangle.east;
|
||||
let y1 = canvasNativeRectangle.north - nativeRectangle.north;
|
||||
let y2 = nativeRectangle.south - canvasNativeRectangle.south;
|
||||
|
||||
let ratioX1 = x1 / (canvasNativeRectangle.east - canvasNativeRectangle.west);
|
||||
if (ratioX1 === Infinity) {
|
||||
ratioX1 = 0;
|
||||
}
|
||||
let ratioX2 = x2 / (canvasNativeRectangle.east - canvasNativeRectangle.west);
|
||||
if (ratioX2 === Infinity) {
|
||||
ratioX2 = 0;
|
||||
}
|
||||
let ratioY1 = y1 / (canvasNativeRectangle.north - canvasNativeRectangle.south);
|
||||
if (ratioY1 === Infinity) {
|
||||
ratioY1 = 0;
|
||||
}
|
||||
let ratioY2 = y2 / (canvasNativeRectangle.north - canvasNativeRectangle.south);
|
||||
if (ratioY2 === Infinity) {
|
||||
ratioY2 = 0;
|
||||
}
|
||||
let differenceX1 = canvas.width * ratioX1;
|
||||
let differenceY1 = canvas.height * ratioY1;
|
||||
let differenceX2 = canvas.width * ratioX2;
|
||||
let differenceY2 = canvas.height * ratioY2;
|
||||
canvas.width = canvas.width - differenceX1 - differenceX2;
|
||||
canvas.height = canvas.height - differenceY1 - differenceY2;
|
||||
if (canvas.width == 0) {
|
||||
canvas.width = 1
|
||||
}
|
||||
if (canvas.height == 0) {
|
||||
canvas.height = 1
|
||||
}
|
||||
|
||||
let y = MaxTileY;
|
||||
let x = MaxTileX;
|
||||
|
||||
let tileArray = []
|
||||
for (let y = MaxTileY; y >= MinTileY; y--) {
|
||||
for (let x = MaxTileX; x >= MinTileX; x--) {
|
||||
tileArray.push({ x, y })
|
||||
}
|
||||
}
|
||||
|
||||
let speed = 30
|
||||
|
||||
let obj = {
|
||||
count: 0
|
||||
};
|
||||
let count = 0;
|
||||
|
||||
let times = -1
|
||||
let obj2 = {
|
||||
count: 0
|
||||
}
|
||||
let count2 = 0
|
||||
Object.defineProperty(obj2, 'count', {
|
||||
get: function () {
|
||||
return count2;
|
||||
},
|
||||
set: function (newValue) {
|
||||
count2 = newValue;
|
||||
if (count2 >= speed) {
|
||||
traversal10()
|
||||
}
|
||||
}
|
||||
});
|
||||
Object.defineProperty(obj, 'count', {
|
||||
get: function () {
|
||||
return count;
|
||||
},
|
||||
set: function (newValue) {
|
||||
count = newValue;
|
||||
progress[i].value = itemTotalCount / itemTotal * itemTotalProgress;
|
||||
let totalProgress = 0
|
||||
for (const key in progress) {
|
||||
totalProgress = totalProgress + progress[key].value
|
||||
}
|
||||
progressBarElm.style.width = totalProgress * 0.99 + '%';
|
||||
rangeNodeActive.style.left = totalProgress * 0.99 + '%';
|
||||
rangeNodeActiveText.innerHTML = Math.floor(totalProgress * 0.99 * 100) / 100 + '%';
|
||||
if (count === (MaxTileX - MinTileX + 1) * (MaxTileY - MinTileY + 1)) {
|
||||
let ctx = canvas.getContext('2d');
|
||||
let cloneCanvas = canvas.cloneNode(true);
|
||||
let cloneCtx = cloneCanvas.getContext('2d');
|
||||
let imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||
cloneCtx.putImageData(imageData, 0, 0);
|
||||
canvas.width = sdk.viewer.canvas.width * scale;
|
||||
canvas.height = sdk.viewer.canvas.height * scale;
|
||||
ctx.drawImage(cloneCanvas, 0, 0, canvas.width, canvas.height);
|
||||
if (totalCanvas) {
|
||||
let ctx = totalCanvas.getContext('2d');
|
||||
ctx.drawImage(canvas, 0, 0);
|
||||
if (countIndex != layerLength) {
|
||||
let m = i += 1;
|
||||
createCanvas(m, totalCanvas);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
let imgBlobData = totalCanvas.toDataURL('image/jpeg', 0.95);
|
||||
const tempCanvas = document.createElement('canvas');
|
||||
const tempCtx = tempCanvas.getContext('2d');
|
||||
tempCanvas.width = totalCanvas.width / scale
|
||||
tempCanvas.height = totalCanvas.height / scale
|
||||
tempCtx.drawImage(totalCanvas, 0, 0, tempCanvas.width, tempCanvas.height);
|
||||
MapPrint(sdk, tempCanvas.toDataURL('image/jpeg', 0.95), rectangle, imgBlobData)
|
||||
progressBarElm.style.width = '100%';
|
||||
rangeNodeActive.style.left = '100%';
|
||||
rangeNodeActiveText.innerHTML = '100%';
|
||||
_this.state = false
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
if (countIndex != layerLength) {
|
||||
let m = i += 1;
|
||||
createCanvas(m, canvas);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
let imgBlobData = canvas.toDataURL('image/jpeg', 0.95);
|
||||
const tempCanvas = document.createElement('canvas');
|
||||
const tempCtx = tempCanvas.getContext('2d');
|
||||
tempCanvas.width = canvas.width / scale;
|
||||
tempCanvas.height = canvas.height / scale;
|
||||
tempCtx.drawImage(canvas, 0, 0, tempCanvas.width, tempCanvas.height);
|
||||
// canvas.width = canvas.width / scale
|
||||
// canvas.height = canvas.height / scale
|
||||
MapPrint(sdk, tempCanvas.toDataURL('image/jpeg', 0.95), rectangle, imgBlobData)
|
||||
progressBarElm.style.width = '100%';
|
||||
rangeNodeActive.style.left = '100%';
|
||||
rangeNodeActiveText.innerHTML = '100%';
|
||||
_this.state = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
if (imageryProvider._readyError) {
|
||||
obj.count = (MaxTileX - MinTileX + 1) * (MaxTileY - MinTileY + 1)
|
||||
}
|
||||
else {
|
||||
traversal10()
|
||||
}
|
||||
|
||||
function traversal10() {
|
||||
obj2.count = 0
|
||||
count2 = 0
|
||||
times++
|
||||
for (let i = times * speed; i < (times + 1) * speed; i++) {
|
||||
if (i >= tileArray.length) {
|
||||
return
|
||||
}
|
||||
traversal(i)
|
||||
}
|
||||
}
|
||||
|
||||
function traversal(i) {
|
||||
if (!_this.state) {
|
||||
return
|
||||
}
|
||||
try {
|
||||
let x = tileArray[i].x
|
||||
if (x < 0) {
|
||||
x = x + OfXTilesAtLevel
|
||||
}
|
||||
const img = new Image();
|
||||
img.setAttribute('crossOrigin', 'anonymous');
|
||||
img.onload = async function () {
|
||||
ctx.drawImage(img, ((tileArray[i].x - MinTileX) * imgWidth) - parseFloat(differenceX1.toFixed(0)), ((tileArray[i].y - MinTileY) * imgHeight) - parseFloat(differenceY1.toFixed(0)), imgWidth, imgHeight);
|
||||
itemTotalCount++;
|
||||
obj.count++;
|
||||
obj2.count++;
|
||||
};
|
||||
img.onerror = function () {
|
||||
itemTotalCount++;
|
||||
obj.count++;
|
||||
obj2.count++;
|
||||
};
|
||||
|
||||
let url;
|
||||
if (imageryProvider.url.indexOf('{x}') !== -1 && imageryProvider.url.indexOf('{y}') !== -1 && imageryProvider.url.indexOf('{z}') !== -1) {
|
||||
url = imageryProvider.url.replace(/\{x\}/g, x).replace(/\{y\}/g, tileArray[i].y).replace(/\{z\}/g, targetLevel);
|
||||
}
|
||||
else if (imageryProvider.url.indexOf('{TileMatrix}') !== -1 && imageryProvider.url.indexOf('{TileRow}') !== -1 && imageryProvider.url.indexOf('{TileCol}') !== -1) {
|
||||
url = imageryProvider.url.replace(/\{TileCol\}/g, x).replace(/\{TileRow\}/g, tileArray[i].y).replace(/\{TileMatrix\}/g, targetLevel);
|
||||
}
|
||||
else if (imageryProvider._layer && imageryProvider._style && imageryProvider._tileMatrixSetID && imageryProvider._format) {
|
||||
url = imageryProvider.url + `&tilematrix=${targetLevel}&layer=${imageryProvider._layer}&style=${imageryProvider._style}&tilerow=${y}&tilecol=${x}&tilematrixset=${imageryProvider._tileMatrixSetID}&format=${imageryProvider._format}`;
|
||||
}
|
||||
else {
|
||||
url = imageryProvider.url + `tile/${targetLevel}/${tileArray[i].y}/${x}`;
|
||||
}
|
||||
img.src = url;
|
||||
} catch (error) {
|
||||
itemTotalCount++;
|
||||
obj.count++;
|
||||
obj2.count++;
|
||||
}
|
||||
}
|
||||
|
||||
function traversal2() {
|
||||
if (!_this.state) {
|
||||
return
|
||||
}
|
||||
try {
|
||||
const img = new Image();
|
||||
img.setAttribute('crossOrigin', 'anonymous');
|
||||
img.onload = async function () {
|
||||
ctx.drawImage(img, ((x - MinTileX) * imgWidth) - parseFloat(differenceX1.toFixed(0)), ((y - MinTileY) * imgHeight) - parseFloat(differenceY1.toFixed(0)), imgWidth, imgHeight);
|
||||
itemTotalCount++;
|
||||
obj.count++;
|
||||
|
||||
if (x > MinTileX) {
|
||||
x--
|
||||
}
|
||||
else {
|
||||
if (y > MinTileY) {
|
||||
y--
|
||||
x = MaxTileX
|
||||
}
|
||||
else {
|
||||
return
|
||||
}
|
||||
}
|
||||
traversal()
|
||||
};
|
||||
|
||||
let url;
|
||||
if (imageryProvider.url.indexOf('{x}') !== -1 && imageryProvider.url.indexOf('{y}') !== -1 && imageryProvider.url.indexOf('{z}') !== -1) {
|
||||
url = imageryProvider.url.replace(/\{x\}/g, x).replace(/\{y\}/g, y).replace(/\{z\}/g, targetLevel);
|
||||
}
|
||||
else if (imageryProvider.url.indexOf('{TileMatrix}') !== -1 && imageryProvider.url.indexOf('{TileRow}') !== -1 && imageryProvider.url.indexOf('{TileCol}') !== -1) {
|
||||
url = imageryProvider.url.replace(/\{TileCol\}/g, x).replace(/\{TileRow\}/g, y).replace(/\{TileMatrix\}/g, targetLevel);
|
||||
}
|
||||
else if (imageryProvider._layer && imageryProvider._style && imageryProvider._tileMatrixSetID && imageryProvider._format) {
|
||||
url = imageryProvider.url + `&tilematrix=${targetLevel}&layer=${imageryProvider._layer}&style=${imageryProvider._style}&tilerow=${y}&tilecol=${x}&tilematrixset=${imageryProvider._tileMatrixSetID}&format=${imageryProvider._format}`;
|
||||
}
|
||||
else {
|
||||
url = imageryProvider.url + `tile/${targetLevel}/${y}/${x}`;
|
||||
}
|
||||
img.src = url;
|
||||
} catch (error) {
|
||||
itemTotalCount++;
|
||||
obj.count++;
|
||||
if (x >= MinTileX) {
|
||||
x--
|
||||
}
|
||||
else {
|
||||
if (y >= MinTileY) {
|
||||
y--
|
||||
x = MaxTileX
|
||||
}
|
||||
else {
|
||||
return
|
||||
}
|
||||
}
|
||||
traversal()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
if (imageryProvider._readyError) {
|
||||
progress[i] = {
|
||||
value: itemTotalProgress
|
||||
}
|
||||
readyPromise()
|
||||
return
|
||||
}
|
||||
imageryProvider.readyPromise.then(() => {
|
||||
readyPromise()
|
||||
}).catch((e) => {
|
||||
imageryProvider._readyError = true
|
||||
progress[i] = {
|
||||
value: itemTotalProgress
|
||||
}
|
||||
readyPromise()
|
||||
});
|
||||
}
|
||||
}
|
||||
desist() {
|
||||
this.state = false
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { ScreenShot, ScreenShotHD }
|
||||
655
src/Global/SheetIndex/index.js
Normal file
655
src/Global/SheetIndex/index.js
Normal file
@ -0,0 +1,655 @@
|
||||
|
||||
import { get2DView } from '../MultiViewportMode'
|
||||
import { getSdk } from '../SplitScreen'
|
||||
import { flyTo } from '../global'
|
||||
import Tools from '../../Tools'
|
||||
|
||||
let tools
|
||||
let state = false
|
||||
let scale = '1:100万'
|
||||
|
||||
function SheetIndexStatusSwitch(sdk, s = false) {
|
||||
if(!sdk) {
|
||||
return
|
||||
}
|
||||
if (!tools) {
|
||||
tools = new Tools()
|
||||
}
|
||||
state = s ? true : false
|
||||
|
||||
if (state) {
|
||||
changeScale(sdk, scale)
|
||||
} else {
|
||||
close(sdk)
|
||||
}
|
||||
let sdk2D = get2DView()
|
||||
if (sdk2D) {
|
||||
if (state) {
|
||||
changeScale(sdk, scale)
|
||||
} else {
|
||||
close(sdk2D)
|
||||
}
|
||||
}
|
||||
|
||||
let sdkD = getSdk().sdkD
|
||||
if(sdkD && sdk !== sdkD) {
|
||||
SheetIndexStatusSwitch(sdkD, s)
|
||||
}
|
||||
|
||||
// return new Promise(async (resolve, reject) => {
|
||||
// setTimeout(() => {
|
||||
// resolve()
|
||||
// }, 1000);
|
||||
// })
|
||||
|
||||
}
|
||||
|
||||
function changeScale(sdk, v) {
|
||||
scale = v
|
||||
if (state) {
|
||||
open(sdk)
|
||||
}
|
||||
let sdk2D = get2DView()
|
||||
if (sdk2D) {
|
||||
if (state) {
|
||||
open(sdk2D)
|
||||
}
|
||||
}
|
||||
return new Promise(async (resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
resolve()
|
||||
}, 1000);
|
||||
})
|
||||
}
|
||||
|
||||
function getStatus() {
|
||||
return state
|
||||
}
|
||||
|
||||
function open(sdk) {
|
||||
close(sdk)
|
||||
let cartographic = sdk.viewer.camera.positionCartographic
|
||||
let options = {
|
||||
position: {
|
||||
lng: Cesium.Math.toDegrees(cartographic.longitude),
|
||||
lat: Cesium.Math.toDegrees(cartographic.latitude),
|
||||
alt: cartographic.height,
|
||||
},
|
||||
}
|
||||
let viewer = sdk.viewer;
|
||||
switch (scale) {
|
||||
case '1:100万':
|
||||
options.position.alt = 16000000
|
||||
break
|
||||
case '1:50万':
|
||||
options.position.alt = 5000000
|
||||
break
|
||||
case '1:25万':
|
||||
options.position.alt = 2300000
|
||||
break
|
||||
case '1:10万':
|
||||
options.position.alt = 680000
|
||||
break
|
||||
case '1:5万':
|
||||
options.position.alt = 385000
|
||||
break
|
||||
case '1:2.5万':
|
||||
options.position.alt = 180000
|
||||
break
|
||||
case '1:1万':
|
||||
options.position.alt = 90000
|
||||
break
|
||||
case '1:5000':
|
||||
options.position.alt = 46000
|
||||
break
|
||||
}
|
||||
|
||||
let gridPrimitives
|
||||
let labelCollection
|
||||
for (let i = 0; i < viewer.scene.primitives._primitives.length; i++) {
|
||||
if (viewer.scene.primitives._primitives[i].name === 'SheetIndexGridPrimitives') {
|
||||
gridPrimitives = viewer.scene.primitives._primitives[i];
|
||||
for (let j = 0; j < gridPrimitives._primitives.length; j++) {
|
||||
if (gridPrimitives._primitives[j].name === 'SheetIndexLabelCollection') {
|
||||
labelCollection = gridPrimitives._primitives[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!gridPrimitives) {
|
||||
gridPrimitives = new Cesium.PrimitiveCollection();
|
||||
gridPrimitives.name = 'SheetIndexGridPrimitives';
|
||||
viewer.scene.primitives.add(gridPrimitives);
|
||||
}
|
||||
if (!labelCollection) {
|
||||
labelCollection = new Cesium.LabelCollection();
|
||||
labelCollection.name = 'SheetIndexLabelCollection';
|
||||
}
|
||||
|
||||
let stationaryFrames = 0;
|
||||
let maxRectangle = null;
|
||||
gridPrimitives.postRenderEvent = () => {
|
||||
let height = sdk.viewer.camera.positionCartographic.height
|
||||
switch (scale) {
|
||||
case '1:100万':
|
||||
options.position.alt = 16000000
|
||||
break
|
||||
case '1:50万':
|
||||
options.position.alt = 5000000
|
||||
break
|
||||
case '1:25万':
|
||||
options.position.alt = 2300000
|
||||
break
|
||||
case '1:10万':
|
||||
options.position.alt = 680000
|
||||
break
|
||||
case '1:5万':
|
||||
options.position.alt = 385000
|
||||
break
|
||||
case '1:2.5万':
|
||||
options.position.alt = 180000
|
||||
break
|
||||
case '1:1万':
|
||||
options.position.alt = 90000
|
||||
break
|
||||
case '1:5000':
|
||||
options.position.alt = 46000
|
||||
break
|
||||
}
|
||||
if (height > options.position.alt * 5) {
|
||||
maxRectangle = null;
|
||||
gridPrimitives.removeAll();
|
||||
return
|
||||
}
|
||||
let isChanged = false
|
||||
let rectangle = getViewExtend();
|
||||
|
||||
let minLng = Cesium.Math.toDegrees(rectangle.west)
|
||||
let minLat = Cesium.Math.toDegrees(rectangle.south)
|
||||
let maxLng = Cesium.Math.toDegrees(rectangle.east)
|
||||
let maxLat = Cesium.Math.toDegrees(rectangle.north)
|
||||
if (minLng > maxLng) {
|
||||
maxLng += 360
|
||||
}
|
||||
rectangle = { minLng, minLat, maxLng, maxLat }
|
||||
if (maxRectangle) {
|
||||
if ((maxRectangle.minLng > rectangle.minLng || maxRectangle.minLat > rectangle.minLat || maxRectangle.maxLng < rectangle.maxLng || maxRectangle.maxLat < rectangle.maxLat) && Cesium.Math.toDegrees(sdk.viewer.camera.pitch) < 0) {
|
||||
isChanged = true
|
||||
}
|
||||
}
|
||||
else {
|
||||
countMapSheet(scale)
|
||||
}
|
||||
|
||||
if (isChanged) {
|
||||
stationaryFrames++;
|
||||
// 确认相机已经静止足够多帧
|
||||
if (stationaryFrames >= 50) {
|
||||
countMapSheet(scale)
|
||||
isChanged = false
|
||||
}
|
||||
} else {
|
||||
stationaryFrames = 0;
|
||||
}
|
||||
}
|
||||
|
||||
options.complete = () => {
|
||||
viewer.scene.postRender.addEventListener(gridPrimitives.postRenderEvent);
|
||||
}
|
||||
flyTo(sdk, options, 0.5)
|
||||
|
||||
/**
|
||||
* 根据比例尺创建图幅线
|
||||
* @param {string} scale - 比例尺(可选值:'1:100万', '1:50万', '1:25万', '1:10万', '1:5万', '1:2.5万', '1:1万', '1:5000')
|
||||
*/
|
||||
function countMapSheet(scale) {
|
||||
labelCollection.removeAll();
|
||||
gridPrimitives.removeAll();
|
||||
labelCollection = new Cesium.LabelCollection();
|
||||
labelCollection.name = 'SheetIndexLabelCollection';
|
||||
gridPrimitives.add(labelCollection);
|
||||
let rectangle = getViewExtend();
|
||||
|
||||
let lngStep // 经度步长
|
||||
let latStep // 纬度步长
|
||||
// let limitLng // 显示界限(根据图幅线数量显隐)
|
||||
// let limitLat
|
||||
// Math.abs(maxLng-minLng)/lngStep, Math.abs(maxLat-minLat)/latStep
|
||||
let scaleByDistance
|
||||
switch (scale) {
|
||||
case '1:100万':
|
||||
lngStep = 6;
|
||||
latStep = 4;
|
||||
scaleByDistance = new Cesium.NearFarScalar(
|
||||
20000000,
|
||||
1,
|
||||
80000000,
|
||||
0
|
||||
)
|
||||
break
|
||||
case '1:50万':
|
||||
lngStep = 3;
|
||||
latStep = 2;
|
||||
scaleByDistance = new Cesium.NearFarScalar(
|
||||
5000000,
|
||||
1,
|
||||
30000000,
|
||||
0
|
||||
)
|
||||
break
|
||||
case '1:25万':
|
||||
lngStep = 1.5;
|
||||
latStep = 1;
|
||||
scaleByDistance = new Cesium.NearFarScalar(
|
||||
2300000,
|
||||
1,
|
||||
20000000,
|
||||
0
|
||||
)
|
||||
break
|
||||
case '1:10万':
|
||||
lngStep = 0.5;
|
||||
latStep = 1 / 3;
|
||||
scaleByDistance = new Cesium.NearFarScalar(
|
||||
680000,
|
||||
1,
|
||||
5000000,
|
||||
0
|
||||
)
|
||||
break
|
||||
case '1:5万':
|
||||
lngStep = 0.25;
|
||||
latStep = 1 / 6;
|
||||
scaleByDistance = new Cesium.NearFarScalar(
|
||||
385000,
|
||||
1,
|
||||
2400000,
|
||||
0
|
||||
)
|
||||
break
|
||||
case '1:2.5万':
|
||||
lngStep = 0.125;
|
||||
latStep = 1 / 12;
|
||||
scaleByDistance = new Cesium.NearFarScalar(
|
||||
180000,
|
||||
1,
|
||||
1200000,
|
||||
0
|
||||
)
|
||||
break
|
||||
case '1:1万':
|
||||
lngStep = 0.0625;
|
||||
latStep = 1 / 24;
|
||||
scaleByDistance = new Cesium.NearFarScalar(
|
||||
90000,
|
||||
1,
|
||||
700000,
|
||||
0
|
||||
)
|
||||
break
|
||||
case '1:5000':
|
||||
lngStep = 0.03125;
|
||||
latStep = 1 / 48;
|
||||
scaleByDistance = new Cesium.NearFarScalar(
|
||||
46000,
|
||||
1,
|
||||
300000,
|
||||
0
|
||||
)
|
||||
break
|
||||
// case '1:1000':
|
||||
// lngStep = 0.01041667;
|
||||
// latStep = 0.00694444;
|
||||
// break
|
||||
// case '1:2000':
|
||||
// lngStep = 0.00520833;
|
||||
// latStep = 0.00347222;
|
||||
// break
|
||||
}
|
||||
|
||||
let minLng = Math.floor((180 + Cesium.Math.toDegrees(rectangle.west)) / lngStep) * lngStep - 180;
|
||||
let minLat = Math.floor((88 + Cesium.Math.toDegrees(rectangle.south)) / latStep) * latStep - 88;
|
||||
let maxLng = Math.ceil((180 + Cesium.Math.toDegrees(rectangle.east)) / lngStep) * lngStep - 180;
|
||||
let maxLat = Math.ceil((88 + Cesium.Math.toDegrees(rectangle.north)) / latStep) * latStep - 88;
|
||||
|
||||
if (minLng > maxLng) {
|
||||
maxLng += 360
|
||||
}
|
||||
|
||||
maxRectangle = { minLng, minLat, maxLng, maxLat }
|
||||
if (minLat < -88) {
|
||||
minLat = -88
|
||||
}
|
||||
if (maxLat > 88) {
|
||||
maxLat = 88
|
||||
}
|
||||
|
||||
if (((maxRectangle.maxLng - maxRectangle.minLng) / lngStep) * ((maxRectangle.maxLat - maxRectangle.minLat) / latStep) > 7000) {
|
||||
maxRectangle = null
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// 绘制经线
|
||||
for (let lng = minLng; lng <= maxLng; lng += lngStep) {
|
||||
const positions = [];
|
||||
let a = []
|
||||
for (let lat = minLat; Math.floor(lat * 1000000000) / 1000000000 <= maxLat; lat += (latStep / 2)) {
|
||||
a.push([lng, lat])
|
||||
positions.push(Cesium.Cartesian3.fromDegrees(lng, lat, 8848));
|
||||
}
|
||||
if (maxLat != 88 && maxLat + (latStep / 2) >= 88) {
|
||||
positions.push(Cesium.Cartesian3.fromDegrees(lng, 88, 8848));
|
||||
}
|
||||
const geometryInstances = new Cesium.GeometryInstance({
|
||||
geometry: new Cesium.PolylineGeometry({
|
||||
positions: positions,
|
||||
width: 1,
|
||||
vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT,
|
||||
arcType: Cesium.ArcType.RHUMB,
|
||||
})
|
||||
});
|
||||
|
||||
gridPrimitives.add(new Cesium.Primitive({
|
||||
geometryInstances: geometryInstances,
|
||||
appearance: new Cesium.PolylineMaterialAppearance({
|
||||
material: Cesium.Material.fromType('Color', {
|
||||
color: Cesium.Color.fromCssColorString('#fcfc00')
|
||||
})
|
||||
})
|
||||
}));
|
||||
|
||||
if (lng < maxLng) {
|
||||
// 计算图幅中心坐标
|
||||
for (let lat = minLat; lat < maxLat; lat += latStep) {
|
||||
let position = { lng: lng + (lngStep / 2), lat: lat + (latStep / 2) };
|
||||
if (position.lat > maxLat) {
|
||||
break
|
||||
}
|
||||
let sheetNumber = calculateMapSheetNumber(position.lng, position.lat, scale);
|
||||
labelCollection.add({
|
||||
position: Cesium.Cartesian3.fromDegrees(position.lng, position.lat, 8848),
|
||||
text: sheetNumber,
|
||||
font: '16px Inter, sans-serif',
|
||||
fillColor: Cesium.Color.fromCssColorString('#fcfc00'),
|
||||
// backgroundColor: Cesium.Color.fromCssColorString('#FFA145'),
|
||||
// backgroundPadding: new Cesium.Cartesian2(8, 4),
|
||||
pixelOffset: new Cesium.Cartesian2(0, 0),
|
||||
showBackground: false,
|
||||
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
||||
scale: 1.0,
|
||||
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 80000000),
|
||||
scaleByDistance: scaleByDistance
|
||||
})
|
||||
// labelCollection.add({
|
||||
// position: Cesium.Cartesian3.fromDegrees(position.lng, position.lat, 10000),
|
||||
// text: position.lng + ' , ' + position.lat,
|
||||
// font: '16px Inter, sans-serif',
|
||||
// fillColor: Cesium.Color.WHITE,
|
||||
// backgroundColor: Cesium.Color.fromCssColorString('#165DFF').withAlpha(0.8),
|
||||
// backgroundPadding: new Cesium.Cartesian2(8, 4),
|
||||
// pixelOffset: new Cesium.Cartesian2(0, 30),
|
||||
// showBackground: true,
|
||||
// verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
// horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
||||
// scale: 1.0,
|
||||
// distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 20000000),
|
||||
// scaleByDistance: new Cesium.NearFarScalar(
|
||||
// 5000000,
|
||||
// 1,
|
||||
// 20000000,
|
||||
// 0
|
||||
// )
|
||||
// })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 绘制纬线
|
||||
for (let lat = minLat; Math.floor(lat * 1000000000) / 1000000000 <= maxLat; lat += latStep) {
|
||||
const positions = [];
|
||||
let a = []
|
||||
for (let lng = minLng; lng <= maxLng; lng += (lngStep / 2)) {
|
||||
a.push([lng, lat])
|
||||
positions.push(Cesium.Cartesian3.fromDegrees(lng, lat, 8848));
|
||||
}
|
||||
const geometryInstances = new Cesium.GeometryInstance({
|
||||
geometry: new Cesium.PolylineGeometry({
|
||||
positions: positions,
|
||||
width: 1,
|
||||
vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT,
|
||||
arcType: Cesium.ArcType.RHUMB,
|
||||
})
|
||||
});
|
||||
|
||||
gridPrimitives.add(new Cesium.Primitive({
|
||||
geometryInstances: geometryInstances,
|
||||
appearance: new Cesium.PolylineMaterialAppearance({
|
||||
material: Cesium.Material.fromType('Color', {
|
||||
color: Cesium.Color.fromCssColorString('#fcfc00')
|
||||
})
|
||||
})
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据经纬度和比例尺计算地图图幅编号
|
||||
* @param {number} longitude - 经度(十进制格式)
|
||||
* @param {number} latitude - 纬度(十进制格式)
|
||||
* @param {string} scale - 比例尺(可选值:'1:100万', '1:50万', '1:25万', '1:10万', '1:5万', '1:2.5万', '1:1万', '1:5000')
|
||||
* @returns {string} 对应的图幅编号
|
||||
*/
|
||||
function calculateMapSheetNumber(lng, lat, scale) {
|
||||
let lngStep // 经度步长
|
||||
let latStep // 纬度步长
|
||||
switch (scale) {
|
||||
case '1:100万':
|
||||
lngStep = 6;
|
||||
latStep = 4;
|
||||
break
|
||||
case '1:50万':
|
||||
lngStep = 3;
|
||||
latStep = 2;
|
||||
break
|
||||
case '1:25万':
|
||||
lngStep = 1.5;
|
||||
latStep = 1;
|
||||
break
|
||||
case '1:10万':
|
||||
lngStep = 0.5;
|
||||
latStep = 1 / 3;
|
||||
break
|
||||
case '1:5万':
|
||||
lngStep = 0.25;
|
||||
latStep = 1 / 6;
|
||||
break
|
||||
case '1:2.5万':
|
||||
lngStep = 0.125;
|
||||
latStep = 1 / 12;
|
||||
break
|
||||
case '1:1万':
|
||||
lngStep = 0.0625;
|
||||
latStep = 1 / 24;
|
||||
break
|
||||
case '1:5000':
|
||||
lngStep = 0.03125;
|
||||
latStep = 1 / 48;
|
||||
break
|
||||
// case '1:1000':
|
||||
// lngStep = 0.01041667;
|
||||
// latStep = 0.00694444;
|
||||
// break
|
||||
// case '1:2000':
|
||||
// lngStep = 0.00520833;
|
||||
// latStep = 0.00347222;
|
||||
// break
|
||||
}
|
||||
// 确保纬度在 -88 到 88 度之间(因为 88° 以上采用特殊分幅)
|
||||
lat = Math.max(-88, Math.min(88, lat));
|
||||
lat = Math.abs(lat); // 取绝对值
|
||||
|
||||
let B6 = 'ABCDEFGHIJKLMNOPQRSTUV'
|
||||
let B2 = lng
|
||||
let B3 = lat
|
||||
|
||||
// 计算 1:100 万地形图的列号
|
||||
const col100W = Math.floor(B2 / 6 + 31);
|
||||
// 1:100 万地形图的行号对应的字母(A-V)
|
||||
const rowChar = B6.charAt(Math.floor(B3 / 4 + 1) - 1);
|
||||
|
||||
// 比例尺代码映射
|
||||
const scaleCodeMap = {
|
||||
'1:100万': '', // 1:100万不需要额外代码
|
||||
'1:50万': 'B',
|
||||
'1:25万': 'C',
|
||||
'1:10万': 'D',
|
||||
'1:5万': 'E',
|
||||
'1:2.5万': 'F',
|
||||
'1:1万': 'G',
|
||||
'1:5000': 'H'
|
||||
};
|
||||
|
||||
|
||||
// 获取比例尺代码
|
||||
const scaleCode = scaleCodeMap[scale];
|
||||
if (!scaleCode && scale !== '1:100万') {
|
||||
throw new Error('不支持的比例尺,请使用: 1:100万, 1:50万, 1:25万, 1:10万, 1:5万, 1:2.5万, 1:1万, 1:5000');
|
||||
}
|
||||
|
||||
// 计算在 1:100 万图幅内的行列号(根据不同比例尺)
|
||||
let rowIn100W, colIn100W;
|
||||
rowIn100W = rowChar + col100W;
|
||||
|
||||
const num1 = Math.floor((Math.ceil(B3 / 4) * 4 - B3) / latStep) + 1;
|
||||
const rowNum = ("000" + num1).slice(-3);
|
||||
const remainder = B2 - Math.floor(B2 / 6) * 6;
|
||||
const num2 = Math.floor(remainder / lngStep) + 1;
|
||||
const colNum = ("000" + num2).slice(-3);
|
||||
|
||||
switch (scale) {
|
||||
case '1:100万':
|
||||
// 1:100万直接使用行号和列号
|
||||
return rowIn100W;
|
||||
case '1:50万':
|
||||
break;
|
||||
case '1:25万':
|
||||
break;
|
||||
case '1:10万':
|
||||
break;
|
||||
|
||||
case '1:5万':
|
||||
break;
|
||||
|
||||
case '1:2.5万':
|
||||
break;
|
||||
|
||||
case '1:1万':
|
||||
break;
|
||||
|
||||
case '1:5000':
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error('不支持的比例尺');
|
||||
}
|
||||
|
||||
// 生成最终编号
|
||||
return rowIn100W + scaleCode + rowNum + colNum;
|
||||
}
|
||||
|
||||
// 获取当前视角矩形范围(二维模式)
|
||||
function getViewExtend() {
|
||||
let params = {};
|
||||
let extend = viewer.camera.computeViewRectangle();
|
||||
if (viewer.scene.mode == 2) {
|
||||
//2D下会可能拾取不到坐标,extend返回undefined,所以做以下转换
|
||||
let canvas = viewer.scene.canvas;
|
||||
let upperLeft = new Cesium.Cartesian2(0, 0);//canvas左上角坐标转2d坐标
|
||||
let lowerRight = new Cesium.Cartesian2(
|
||||
canvas.clientWidth,
|
||||
canvas.clientHeight
|
||||
);//canvas右下角坐标转2d坐标
|
||||
|
||||
let ellipsoid = viewer.scene.globe.ellipsoid;
|
||||
let upperLeft3 = viewer.camera.pickEllipsoid(
|
||||
upperLeft,
|
||||
ellipsoid
|
||||
);//2D转3D世界坐标
|
||||
|
||||
let lowerRight3 = viewer.camera.pickEllipsoid(
|
||||
lowerRight,
|
||||
ellipsoid
|
||||
);//2D转3D世界坐标
|
||||
|
||||
if (!upperLeft3) {
|
||||
let cartesian2 = Cesium.SceneTransforms.wgs84ToWindowCoordinates(viewer.scene, { x: 0, y: 0, z: 6356755 });
|
||||
upperLeft.y = cartesian2.y + 5
|
||||
upperLeft3 = viewer.camera.pickEllipsoid(
|
||||
upperLeft,
|
||||
ellipsoid
|
||||
);
|
||||
}
|
||||
if (!lowerRight3) {
|
||||
let cartesian2 = Cesium.SceneTransforms.wgs84ToWindowCoordinates(viewer.scene, { x: 0, y: 0, z: -6356755 });
|
||||
lowerRight.y = cartesian2.y - 5
|
||||
lowerRight3 = viewer.camera.pickEllipsoid(
|
||||
lowerRight,
|
||||
ellipsoid
|
||||
);
|
||||
// console.log('lowerRight3', lowerRight, lowerRight3)
|
||||
}
|
||||
let upperLeftCartographic = viewer.scene.globe.ellipsoid.cartesianToCartographic(
|
||||
upperLeft3
|
||||
);//3D世界坐标转弧度
|
||||
let lowerRightCartographic = viewer.scene.globe.ellipsoid.cartesianToCartographic(
|
||||
lowerRight3
|
||||
);//3D世界坐标转弧度
|
||||
|
||||
if ((lowerRight.y - upperLeft.y) / (lowerRight.x - upperLeft.x) <= 0.49998752339363695) {
|
||||
extend = new Cesium.Rectangle(Cesium.Math.toRadians(-180), Cesium.Math.toRadians(-90), Cesium.Math.toRadians(180), Cesium.Math.toRadians(90))
|
||||
}
|
||||
else {
|
||||
extend = new Cesium.Rectangle(upperLeftCartographic.longitude, lowerRightCartographic.latitude, lowerRightCartographic.longitude, upperLeftCartographic.latitude);
|
||||
}
|
||||
|
||||
// console.log("经度:" + minx + "----" + maxx);
|
||||
// console.log("纬度:" + miny + "----" + maxy);
|
||||
|
||||
return extend;
|
||||
} else {
|
||||
//3D获取方式
|
||||
return extend;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
function close(sdk) {
|
||||
let viewer = sdk.viewer;
|
||||
let gridPrimitives
|
||||
let labelCollection
|
||||
for (let i = 0; i < viewer.scene.primitives._primitives.length; i++) {
|
||||
if (viewer.scene.primitives._primitives[i].name === 'SheetIndexGridPrimitives') {
|
||||
gridPrimitives = viewer.scene.primitives._primitives[i];
|
||||
for (let j = 0; j < gridPrimitives._primitives.length; j++) {
|
||||
if (gridPrimitives._primitives[j].name === 'SheetIndexLabelCollection') {
|
||||
labelCollection = gridPrimitives._primitives[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
labelCollection && (labelCollection.removeAll());
|
||||
gridPrimitives && (gridPrimitives.removeAll());
|
||||
gridPrimitives && (viewer.scene.postRender.removeEventListener(gridPrimitives.postRenderEvent));
|
||||
}
|
||||
|
||||
export { SheetIndexStatusSwitch, changeScale, getStatus }
|
||||
30
src/Global/Skin/index.js
Normal file
30
src/Global/Skin/index.js
Normal file
@ -0,0 +1,30 @@
|
||||
let theme = {
|
||||
"yingguangse": new Map(),
|
||||
"gonganlan": new Map(),
|
||||
"hong": new Map(),
|
||||
}
|
||||
// 主色
|
||||
theme.yingguangse.set("--color-sdk-base", "#00ffff")
|
||||
// 辅色
|
||||
theme.yingguangse.set("--color-sdk-auxiliary", "#004242")
|
||||
theme.yingguangse.set("--color-sdk-auxiliary-public", "#ffffff")
|
||||
// 预警色
|
||||
theme.yingguangse.set("--color-sdk-warning-0", "#1BF8C3")
|
||||
theme.yingguangse.set("--color-sdk-warning-1", "#F16C55")
|
||||
theme.yingguangse.set("--color-sdk-warning-2", "#FFA145")
|
||||
theme.yingguangse.set("--color-sdk-warning-3", "#FFDF53")
|
||||
// 文本色
|
||||
theme.yingguangse.set("--color-sdk-text-head", "#FFFFFF")
|
||||
theme.yingguangse.set("--color-sdk-text-head-1", "#E6F7FF")
|
||||
theme.yingguangse.set("--color-sdk-text-head-2", "#ADF1FF")
|
||||
// 渐变色
|
||||
theme.yingguangse.set("--color-sdk-gradual", "#00ffff 6.25%, #00ffff 100%")
|
||||
theme.yingguangse.set("--color-sdk-bg-gradual", "#00ffff33 0%, #00ffff00 100%")
|
||||
|
||||
export default theme;
|
||||
|
||||
function setSkin(name) {
|
||||
document.documentElement.style.setProperty('--color-sdk-base', 'rgba(0, 55, 55, 1)');
|
||||
}
|
||||
|
||||
export { setSkin }
|
||||
578
src/Global/SplitScreen/ClickCallback/index.js
Normal file
578
src/Global/SplitScreen/ClickCallback/index.js
Normal file
@ -0,0 +1,578 @@
|
||||
/**
|
||||
* @name: click
|
||||
* @author: Administrator
|
||||
* @date: 2023-05-28 11:05
|
||||
* @description:click
|
||||
* @update: 2023-05-28 11:05
|
||||
*/
|
||||
let leftClickHandler = null
|
||||
let rightClickHandler = null
|
||||
let MoveHandler = null
|
||||
let leftClickCallbackMap = new Map()
|
||||
let rightClickCallbackMap = new Map()
|
||||
let MoveCallbackMap = new Map()
|
||||
let selectedFeature;
|
||||
|
||||
|
||||
function cartesian3Towgs84(cartesian, viewer) {
|
||||
var ellipsoid = viewer.scene.globe.ellipsoid
|
||||
var cartesian3 = new Cesium.Cartesian3(
|
||||
cartesian.x,
|
||||
cartesian.y,
|
||||
cartesian.z
|
||||
)
|
||||
var cartographic = ellipsoid.cartesianToCartographic(cartesian3)
|
||||
var lat = Cesium.Math.toDegrees(cartographic.latitude)
|
||||
var lng = Cesium.Math.toDegrees(cartographic.longitude)
|
||||
var alt = cartographic.height < 0 ? 0 : cartographic.height
|
||||
return {
|
||||
lng: lng,
|
||||
lat: lat,
|
||||
alt: alt,
|
||||
}
|
||||
}
|
||||
|
||||
function getcartesian(sdk, movement) {
|
||||
if (movement.endPosition) {
|
||||
movement.endPosition.y -= 2
|
||||
}
|
||||
let position = movement.position || movement.endPosition
|
||||
// 获取世界坐标系地表坐标,考虑地形,不包括模型,倾斜摄影模型表面;
|
||||
let cartesian = sdk.viewer.scene.pickPosition(position)
|
||||
if (!cartesian) {
|
||||
const ray = sdk.viewer.camera.getPickRay(position); //相交的射线
|
||||
cartesian = sdk.viewer.scene.globe.pick(ray, sdk.viewer.scene);
|
||||
}
|
||||
return cartesian
|
||||
}
|
||||
|
||||
function openLeftClick(sdk, cb) {
|
||||
if (!sdk || !sdk.viewer) {
|
||||
return
|
||||
}
|
||||
let click = true
|
||||
leftClickHandler = new Cesium.ScreenSpaceEventHandler(sdk.viewer.canvas)
|
||||
leftClickHandler.setInputAction((movement) => {
|
||||
let cartesian = sdk.viewer.scene.pickPosition(movement.position)
|
||||
if (!cartesian) {
|
||||
const ray = sdk.viewer.camera.getPickRay(movement.position); //相交的射线
|
||||
cartesian = sdk.viewer.scene.globe.pick(ray, sdk.viewer.scene);
|
||||
}
|
||||
if (!cartesian) {
|
||||
return
|
||||
}
|
||||
|
||||
let pos84 = cartesian3Towgs84(cartesian, sdk.viewer)
|
||||
|
||||
cb && cb(pos84)
|
||||
|
||||
if (click) {
|
||||
click = false
|
||||
setTimeout(() => {
|
||||
click = true
|
||||
}, 600);
|
||||
if (!YJ.Measure.GetMeasureStatus() && cartesian) {
|
||||
let flag = false
|
||||
for (let i = leftClickCallbackMap.size - 1; i >= 0; i--) {
|
||||
let key = Array.from(leftClickCallbackMap.keys())[i]
|
||||
let obj = leftClickCallbackMap.get(key)
|
||||
if (obj) {
|
||||
|
||||
if (obj.that) {
|
||||
// 是否为多边形
|
||||
if (obj.that.type === 'PolygonObject') {
|
||||
// 是否可点击y
|
||||
if (obj.that.picking) {
|
||||
if (obj.that.options.positions && obj.that.options.positions.length >= 3) {
|
||||
let pt = turf.point([pos84.lng, pos84.lat]);
|
||||
let polyPos = []
|
||||
for (let i = 0; i < obj.that.options.positions.length; i++) {
|
||||
polyPos.push([
|
||||
obj.that.options.positions[i].lng,
|
||||
obj.that.options.positions[i].lat
|
||||
])
|
||||
}
|
||||
polyPos.push([
|
||||
obj.that.options.positions[0].lng,
|
||||
obj.that.options.positions[0].lat
|
||||
])
|
||||
let poly = turf.polygon([polyPos]);
|
||||
let contain = turf.booleanPointInPolygon(pt, poly);
|
||||
if (contain) {
|
||||
obj.callback(
|
||||
movement,
|
||||
obj.that.options.id,
|
||||
cartesian3Towgs84(getcartesian(sdk, movement), sdk.viewer), obj.that)
|
||||
flag = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 聚集地
|
||||
else if (obj.that.type === 'AssembleObject') {
|
||||
if (obj.that.picking) {
|
||||
if (obj.that.options.positions && obj.that.options.positions.length >= 3) {
|
||||
let positions = obj.that.computeAssemble(obj.that.options.positions, true)
|
||||
let pt = turf.point([pos84.lng, pos84.lat]);
|
||||
let polyPos = []
|
||||
for (let i = 0; i < positions.length; i += 2) {
|
||||
polyPos.push([
|
||||
positions[i],
|
||||
positions[i + 1]
|
||||
])
|
||||
}
|
||||
let poly = turf.polygon([polyPos]);
|
||||
let contain = turf.booleanPointInPolygon(pt, poly);
|
||||
if (contain) {
|
||||
obj.callback(
|
||||
movement,
|
||||
obj.that.options.id,
|
||||
cartesian3Towgs84(getcartesian(sdk, movement), sdk.viewer), obj.that)
|
||||
flag = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 单箭头
|
||||
else if (obj.that.type === 'AttackArrowObject') {
|
||||
if (obj.that.picking) {
|
||||
if (obj.that.options.positions && obj.that.options.positions.length >= 3) {
|
||||
let pt = turf.point([pos84.lng, pos84.lat]);
|
||||
let positions = obj.that.computeAttackArrow(obj.that.options.positions)
|
||||
let polyPos = []
|
||||
for (let m = 0; m < positions.length; m++) {
|
||||
let pos84 = cartesian3Towgs84(positions[m], sdk.viewer)
|
||||
polyPos.push([pos84.lng, pos84.lat])
|
||||
}
|
||||
let poly = turf.polygon([polyPos]);
|
||||
let contain = turf.booleanPointInPolygon(pt, poly);
|
||||
if (contain) {
|
||||
obj.callback(
|
||||
movement,
|
||||
obj.that.options.id,
|
||||
cartesian3Towgs84(getcartesian(sdk, movement), sdk.viewer), obj.that)
|
||||
flag = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 双箭头
|
||||
else if (obj.that.type === 'PincerArrowObject') {
|
||||
if (obj.that.picking) {
|
||||
if (obj.that.options.positions && obj.that.options.positions.length >= 5) {
|
||||
let pt = turf.point([pos84.lng, pos84.lat]);
|
||||
let positions = obj.that.computePincerArrow(obj.that.options.positions)
|
||||
let polyPos = []
|
||||
for (let m = 0; m < positions.length; m++) {
|
||||
let pos84 = cartesian3Towgs84(positions[m], sdk.viewer)
|
||||
polyPos.push([pos84.lng, pos84.lat])
|
||||
}
|
||||
let pos84_0 = cartesian3Towgs84(positions[0], sdk.viewer)
|
||||
polyPos.push([pos84_0.lng, pos84_0.lat])
|
||||
let poly = turf.polygon([polyPos]);
|
||||
let contain = turf.booleanPointInPolygon(pt, poly);
|
||||
if (contain) {
|
||||
obj.callback(
|
||||
movement,
|
||||
obj.that.options.id,
|
||||
cartesian3Towgs84(getcartesian(sdk, movement), sdk.viewer), obj.that)
|
||||
flag = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 圆
|
||||
else if (obj.that.type === 'CircleObject') {
|
||||
if (obj.that.picking) {
|
||||
let pt = turf.point([pos84.lng, pos84.lat]);
|
||||
if (obj.that.options.center && obj.that.options.radius) {
|
||||
let center = [obj.that.options.center.lng, obj.that.options.center.lat];
|
||||
let radius = obj.that.options.radius / 1000;
|
||||
let options = { steps: 360, units: 'kilometers' };
|
||||
let circle = turf.circle(center, radius, options);
|
||||
let contain = turf.booleanPointInPolygon(pt, circle);
|
||||
if (contain) {
|
||||
obj.callback(
|
||||
movement,
|
||||
obj.that.options.id,
|
||||
cartesian3Towgs84(getcartesian(sdk, movement), sdk.viewer), obj.that)
|
||||
flag = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
// 扇形
|
||||
else if (obj.that.type === 'SectorObject') {
|
||||
if (obj.that.picking) {
|
||||
let pt = turf.point([pos84.lng, pos84.lat]);
|
||||
if (obj.that.options.center && obj.that.options.radius && obj.that.options.startAngle && obj.that.options.endAngle) {
|
||||
let positions = obj.that.calSector(obj.that.options.center, obj.that.options.radius, obj.that.options.startAngle, obj.that.options.endAngle, undefined, true)
|
||||
let polyPos = []
|
||||
for (let m = 0; m < positions.length; m++) {
|
||||
polyPos.push([positions[m].lng, positions[m].lat])
|
||||
}
|
||||
let poly = turf.polygon([polyPos]);
|
||||
let contain = turf.booleanPointInPolygon(pt, poly);
|
||||
if (contain) {
|
||||
obj.callback(
|
||||
movement,
|
||||
obj.that.options.id,
|
||||
cartesian3Towgs84(getcartesian(sdk, movement), sdk.viewer), obj.that)
|
||||
flag = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!flag) {
|
||||
const pick = sdk.viewer.scene.pick(movement.position)
|
||||
if (pick) {
|
||||
if (pick.id) {
|
||||
let entityId
|
||||
// 矢量
|
||||
if (pick.id.type && pick.id.type === 'vector' && pick.id.parentId) {
|
||||
let obj = leftClickCallbackMap.get(pick.id.parentId)
|
||||
if (obj.that.picking && obj.that.geojson) {
|
||||
for (let i = 0; i < obj.that.geojson.features.length; i++) {
|
||||
if (obj.that.geojson.features[i].id === pick.id._id) {
|
||||
obj.callback(
|
||||
movement,
|
||||
obj.that.geojson.features[i].id,
|
||||
cartesian3Towgs84(getcartesian(sdk, movement), sdk.viewer), obj.that)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (typeof pick.id.id == 'string') {
|
||||
let array = pick.id.id.split('-')
|
||||
array.splice(array.length - 1, 1)
|
||||
entityId = array.join('-')
|
||||
}
|
||||
|
||||
if (pick.id.properties && pick.id.properties.id && leftClickCallbackMap.has(pick.id.properties.id._value)) {
|
||||
let obj = leftClickCallbackMap.get(pick.id.properties.id._value)
|
||||
if (obj.that.picking) {
|
||||
obj.callback(
|
||||
movement,
|
||||
pick.id.properties.id._value,
|
||||
cartesian3Towgs84(getcartesian(sdk, movement), sdk.viewer), obj.that)
|
||||
}
|
||||
}
|
||||
else if (leftClickCallbackMap.has(pick.id.id)) {
|
||||
let obj = leftClickCallbackMap.get(pick.id.id)
|
||||
if (obj.that.picking) {
|
||||
obj.callback(
|
||||
movement,
|
||||
pick.id.id,
|
||||
cartesian3Towgs84(getcartesian(sdk, movement), sdk.viewer), obj.that)
|
||||
}
|
||||
}
|
||||
else if (entityId && leftClickCallbackMap.has(entityId)) {
|
||||
let obj = leftClickCallbackMap.get(entityId)
|
||||
if (obj.that.picking) {
|
||||
obj.callback(
|
||||
movement,
|
||||
entityId,
|
||||
cartesian3Towgs84(getcartesian(sdk, movement), sdk.viewer), obj.that)
|
||||
}
|
||||
}
|
||||
else if (pick.primitive) {
|
||||
if (typeof pick.id == 'string' && leftClickCallbackMap.has(pick.id)) {
|
||||
let obj = leftClickCallbackMap.get(pick.id)
|
||||
obj.callback(
|
||||
movement,
|
||||
pick.id,
|
||||
cartesian3Towgs84(getcartesian(sdk, movement), sdk.viewer), obj.that)
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (pick.primitive && pick.primitive.id) {
|
||||
if (leftClickCallbackMap.has(pick.primitive.id)) {
|
||||
let obj = leftClickCallbackMap.get(pick.primitive.id)
|
||||
if (obj.that.picking) {
|
||||
if (obj.that.type === 'bim') {
|
||||
if (YJ.Global.getBimPickStatus(sdk)) {
|
||||
obj.callback(
|
||||
movement,
|
||||
pick.primitive,
|
||||
cartesian3Towgs84(getcartesian(sdk, movement), sdk.viewer), obj.that)
|
||||
}
|
||||
}
|
||||
else {
|
||||
obj.callback(
|
||||
movement,
|
||||
pick.primitive.id,
|
||||
cartesian3Towgs84(getcartesian(sdk, movement), sdk.viewer), obj.that)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pick.content && (!pick.primitive || !pick.primitive.id)) {
|
||||
if (leftClickCallbackMap.has(pick.content.tileset.id)) {
|
||||
let obj = leftClickCallbackMap.get(pick.content.tileset.id)
|
||||
if (obj.that.picking) {
|
||||
if (obj.that.type === 'bim') {
|
||||
if (YJ.Global.getBimPickStatus(sdk)) {
|
||||
obj.callback(
|
||||
movement,
|
||||
pick.content.tileset,
|
||||
cartesian3Towgs84(getcartesian(sdk, movement), sdk.viewer), obj.that)
|
||||
}
|
||||
}
|
||||
else {
|
||||
obj.callback(
|
||||
movement,
|
||||
pick.content.tileset.id,
|
||||
cartesian3Towgs84(getcartesian(sdk, movement), sdk.viewer), obj.that)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// if (click) {
|
||||
// click = false
|
||||
// setTimeout(() => {
|
||||
// click = true
|
||||
// }, 300);
|
||||
// if (!YJ.Measure.GetMeasureStatus()) {
|
||||
|
||||
// }
|
||||
// }
|
||||
}, Cesium.ScreenSpaceEventType.LEFT_CLICK)
|
||||
|
||||
// leftClickHandler.setInputAction(function (movement) {
|
||||
// const feature = sdk.viewer.scene.pick(movement.endPosition);
|
||||
// // unselectFeature(selectedFeature);
|
||||
// if (selectedFeature) {
|
||||
// selectedFeature.color = Cesium.Color.WHITE;
|
||||
// }
|
||||
// selectedFeature = feature
|
||||
// if (feature) {
|
||||
// feature.color = Cesium.Color.YELLOW;
|
||||
// }
|
||||
// }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
function closeLeftClick(sdk) {
|
||||
leftClickHandler.destroy() //关闭事件句柄
|
||||
leftClickHandler = null
|
||||
// }
|
||||
}
|
||||
|
||||
function openRightClick(sdk) {
|
||||
if (!sdk || !sdk.viewer) {
|
||||
return
|
||||
}
|
||||
rightClickHandler = new Cesium.ScreenSpaceEventHandler(sdk.viewer.canvas)
|
||||
rightClickHandler.setInputAction((movement) => {
|
||||
if (!YJ.Measure.GetMeasureStatus()) {
|
||||
const pick = sdk.viewer.scene.pick(movement.position)
|
||||
if (pick && pick.id) {
|
||||
let id
|
||||
if (pick.id.type && pick.id.type === 'vector' && pick.id.parentId) {
|
||||
let obj = rightClickCallbackMap.get(pick.id.parentId)
|
||||
if (obj.that.picking && obj.that.geojson) {
|
||||
for (let i = 0; i < obj.that.geojson.features.length; i++) {
|
||||
if (obj.that.geojson.features[i].id === pick.id._id) {
|
||||
obj.callback(
|
||||
movement,
|
||||
obj.that.geojson.features[i].id,
|
||||
cartesian3Towgs84(getcartesian(sdk, movement), sdk.viewer), obj.that)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (typeof pick.id === 'string') {
|
||||
id = pick.id
|
||||
}
|
||||
else {
|
||||
id = pick.id.id
|
||||
}
|
||||
if (rightClickCallbackMap.has(id)) {
|
||||
let obj = rightClickCallbackMap.get(id)
|
||||
if (obj.that.picking) {
|
||||
let cartesian = getcartesian(sdk, movement)
|
||||
if (!cartesian) {
|
||||
return
|
||||
}
|
||||
obj.callback(
|
||||
movement,
|
||||
id,
|
||||
cartesian3Towgs84(cartesian, sdk.viewer), obj.that)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pick && pick.content) {
|
||||
if (rightClickCallbackMap.has(pick.content.tileset.id)) {
|
||||
let obj = rightClickCallbackMap.get(pick.content.tileset.id)
|
||||
if (obj.that.picking) {
|
||||
if (obj.that.type === 'bim') {
|
||||
if (YJ.Global.getBimPickStatus(sdk)) {
|
||||
let cartesian = getcartesian(sdk, movement)
|
||||
if (!cartesian) {
|
||||
return
|
||||
}
|
||||
obj.callback(
|
||||
movement,
|
||||
pick.getProperty('id'),
|
||||
cartesian3Towgs84(cartesian, sdk.viewer), obj.that)
|
||||
}
|
||||
}
|
||||
else {
|
||||
let cartesian = getcartesian(sdk, movement)
|
||||
if (!cartesian) {
|
||||
return
|
||||
}
|
||||
obj.callback(
|
||||
movement,
|
||||
pick.content.tileset.id,
|
||||
cartesian3Towgs84(cartesian, sdk.viewer), obj.that)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK)
|
||||
}
|
||||
|
||||
function closeRightClick() {
|
||||
if (rightClickHandler) {
|
||||
rightClickHandler.destroy() //关闭事件句柄
|
||||
rightClickHandler = null
|
||||
}
|
||||
}
|
||||
|
||||
function openMove(sdk) {
|
||||
MoveHandler = new Cesium.ScreenSpaceEventHandler(sdk.viewer.canvas)
|
||||
MoveHandler.setInputAction(function (movement) {
|
||||
const pick = sdk.viewer.scene.pick(movement.endPosition);
|
||||
// unselectFeature(selectedFeature);
|
||||
// if (selectedFeature) {
|
||||
// let color = '#fff'
|
||||
// let state = selectedFeature.getProperty('state')
|
||||
// switch (state) {
|
||||
// case '0':
|
||||
// color = '#fff'
|
||||
// break;
|
||||
// case '1':
|
||||
// color = '#f00'
|
||||
// break;
|
||||
// case '2':
|
||||
// color = '#0f0'
|
||||
// break;
|
||||
// case '3':
|
||||
// color = '#00f'
|
||||
// break;
|
||||
// default:
|
||||
// }
|
||||
// selectedFeature.color = Cesium.Color.fromCssColorString(color).withAlpha(selectedFeature.tileset.transparency)
|
||||
// }
|
||||
// if (pick && pick.id) { }
|
||||
// if (pick && pick.content) {
|
||||
// if (MoveCallbackMap.has(pick.content.tileset.id)) {
|
||||
// let obj = MoveCallbackMap.get(pick.content.tileset.id)
|
||||
// if (obj.that.picking) {
|
||||
// if (obj.that.type === 'bim') {
|
||||
// if (YJ.Global.getBimPickStatus(sdk)) {
|
||||
// selectedFeature = pick
|
||||
// pick.color = Cesium.Color.YELLOW;
|
||||
// }
|
||||
// else {
|
||||
// selectedFeature = null
|
||||
// }
|
||||
// }
|
||||
// else {
|
||||
// selectedFeature = pick
|
||||
// pick.color = Cesium.Color.YELLOW;
|
||||
// }
|
||||
// }
|
||||
// else {
|
||||
// selectedFeature = null
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
|
||||
}
|
||||
|
||||
function closeMove() {
|
||||
if (MoveHandler) {
|
||||
MoveHandler.destroy() //关闭事件句柄
|
||||
MoveHandler = null
|
||||
}
|
||||
}
|
||||
|
||||
/*注册左键回调*/
|
||||
function regLeftClickCallback(id, callback, that) {
|
||||
|
||||
leftClickCallbackMap.set(id, { callback, that })
|
||||
}/*取消左键回调*/
|
||||
function unRegLeftClickCallback(id,) {
|
||||
leftClickCallbackMap.delete(id,)
|
||||
}
|
||||
|
||||
/*注册右键回调*/
|
||||
function regRightClickCallback(id, callback, that) {
|
||||
rightClickCallbackMap.set(id, { callback, that })
|
||||
}/*取消右键回调*/
|
||||
function unRegRightClickCallback(id,) {
|
||||
rightClickCallbackMap.delete(id,)
|
||||
}
|
||||
|
||||
/*注册左键回调*/
|
||||
function regMoveCallback(id, callback, that) {
|
||||
MoveCallbackMap.set(id, { callback, that })
|
||||
}/*取消左键回调*/
|
||||
function unregMoveCallback(id,) {
|
||||
MoveCallbackMap.delete(id,)
|
||||
}
|
||||
|
||||
function getLeftClickState() {
|
||||
if (leftClickHandler) {
|
||||
return true
|
||||
}
|
||||
else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
function getRightClickState() {
|
||||
if (rightClickHandler) {
|
||||
return true
|
||||
}
|
||||
else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
function getMoveState() {
|
||||
if (MoveHandler) {
|
||||
return true
|
||||
}
|
||||
else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export { openLeftClick, closeLeftClick, regLeftClickCallback, unRegLeftClickCallback, openRightClick, closeRightClick, regRightClickCallback, unRegRightClickCallback, openMove, closeMove, regMoveCallback, unregMoveCallback, getLeftClickState, getRightClickState, getMoveState }
|
||||
1441
src/Global/SplitScreen/index.js
Normal file
1441
src/Global/SplitScreen/index.js
Normal file
File diff suppressed because it is too large
Load Diff
366
src/Global/cluster/cluster.js
Normal file
366
src/Global/cluster/cluster.js
Normal file
@ -0,0 +1,366 @@
|
||||
|
||||
|
||||
/*
|
||||
let datasource=null
|
||||
let dataSourcePromise = null
|
||||
// let enabled = true
|
||||
let dataSourcexg = null
|
||||
function createCluster(viewer) {
|
||||
datasource = new Cesium.CustomDataSource("dataSource1");
|
||||
dataSourcePromise = viewer.dataSources.add(datasource);
|
||||
dataSourcePromise.then((dataSource)=> {
|
||||
// return;
|
||||
const pixelRange = 15;
|
||||
const minimumClusterSize = 3;
|
||||
const enabled = false;
|
||||
dataSourcexg = dataSource
|
||||
|
||||
dataSource.clustering.enabled = enabled; //聚合开启
|
||||
dataSource.clustering.pixelRange = pixelRange; //设置像素范围,以扩展显示边框
|
||||
dataSource.clustering.minimumClusterSize = minimumClusterSize; //设置最小的聚合点数目,超过此数目才能聚合
|
||||
|
||||
let removeListener;
|
||||
|
||||
//按聚合层级创建对应图标
|
||||
const pinBuilder = new Cesium.PinBuilder();
|
||||
// console.log('pinBuilder',pinBuilder);
|
||||
var pin100 = pinBuilder
|
||||
.fromText("100+", Cesium.Color.BLUE, 48)
|
||||
.toDataURL();
|
||||
var pin50 = pinBuilder
|
||||
.fromText("50+", Cesium.Color.BLUE, 48)
|
||||
.toDataURL();
|
||||
var pin40 = pinBuilder
|
||||
.fromText("40+", Cesium.Color.RED, 48)
|
||||
.toDataURL();
|
||||
var pin30 = pinBuilder
|
||||
.fromText("30+", Cesium.Color.RED, 48)
|
||||
.toDataURL();
|
||||
var pin20 = pinBuilder
|
||||
.fromText("20+", Cesium.Color.RED, 48)
|
||||
.toDataURL();
|
||||
var pin10 = pinBuilder
|
||||
.fromText("10+", Cesium.Color.RED, 48)
|
||||
.toDataURL();
|
||||
// 10以内聚合图标
|
||||
const singleDigitPins = new Array(8);
|
||||
for (let i = 0; i < singleDigitPins.length; ++i) {
|
||||
singleDigitPins[i] = pinBuilder
|
||||
.fromText(`${i + 2}`, Cesium.Color.VIOLET, 48)
|
||||
.toDataURL();
|
||||
}
|
||||
|
||||
|
||||
function customStyle() {
|
||||
if (Cesium.defined(removeListener)) {
|
||||
removeListener();
|
||||
removeListener = undefined;
|
||||
} else {
|
||||
removeListener = dataSource.clustering.clusterEvent.addEventListener(
|
||||
function(clusteredEntities, cluster) {
|
||||
cluster.label.show = false;
|
||||
cluster.billboard.show = true;
|
||||
cluster.billboard.id = cluster.label.id;
|
||||
cluster.billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM;
|
||||
if (clusteredEntities.length >= 100) {
|
||||
cluster.billboard.image = pin100;
|
||||
} else if (clusteredEntities.length >= 50) {
|
||||
cluster.billboard.image = pin50;
|
||||
} else if (clusteredEntities.length >= 40) {
|
||||
cluster.billboard.image = pin40;
|
||||
} else if (clusteredEntities.length >= 30) {
|
||||
cluster.billboard.image = pin30;
|
||||
} else if (clusteredEntities.length >= 20) {
|
||||
cluster.billboard.image = pin20;
|
||||
} else if (clusteredEntities.length >= 10) {
|
||||
cluster.billboard.image = pin10;
|
||||
} else {
|
||||
cluster.billboard.image =
|
||||
singleDigitPins[clusteredEntities.length - 2];
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// force a re-cluster with the new styling
|
||||
const pixelRange = dataSource.clustering.pixelRange;
|
||||
dataSource.clustering.pixelRange = 0;
|
||||
dataSource.clustering.pixelRange = pixelRange;
|
||||
}
|
||||
|
||||
customStyle();
|
||||
|
||||
var viewModel = {
|
||||
pixelRange: pixelRange,
|
||||
minimumClusterSize: minimumClusterSize,
|
||||
};
|
||||
Cesium.knockout.track(viewModel);
|
||||
|
||||
|
||||
function subscribeParameter(name) {
|
||||
Cesium.knockout
|
||||
.getObservable(viewModel, name)
|
||||
.subscribe(function (newValue) {
|
||||
dataSource.clustering[name] = newValue;
|
||||
});
|
||||
}
|
||||
|
||||
subscribeParameter("pixelRange");
|
||||
subscribeParameter("minimumClusterSize");
|
||||
});
|
||||
}
|
||||
|
||||
function addCluster(entity) {
|
||||
datasource.entities.add(entity)
|
||||
}
|
||||
function remove_entity_from_cluster(entity) {
|
||||
datasource.entities.remove(entity)
|
||||
}
|
||||
|
||||
function switchCluster(status){
|
||||
dataSourcexg.clustering.enabled = status
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
import Tools from '../../Tools'
|
||||
import {
|
||||
getGroundCover
|
||||
} from '../../Global/global'
|
||||
|
||||
|
||||
/*创建聚合,只能聚合point ,billboard,label*/
|
||||
function createCluster(viewer) {
|
||||
let tools = new Tools()
|
||||
let cluster = new Cesium.CustomDataSource("sdk-dataSource1")
|
||||
let dataSourcePromise = viewer.dataSources.add(cluster)
|
||||
dataSourcePromise.then(dataSource => {
|
||||
// if (!get2DView()) {
|
||||
// dataSource.entities.collectionChanged.addEventListener((entities) => {
|
||||
// syncDataSources(dataSource, 'entities')
|
||||
// })
|
||||
// }
|
||||
var pixelRange = 15;
|
||||
var minimumClusterSize = 2;
|
||||
var enabled = false;
|
||||
dataSource.clustering.enabled = enabled;
|
||||
dataSource.clustering.pixelRange = pixelRange;
|
||||
dataSource.clustering.minimumClusterSize = minimumClusterSize;
|
||||
var removeListener;
|
||||
|
||||
var pinBuilder = new Cesium.PinBuilder();
|
||||
var pin50 = pinBuilder
|
||||
.fromText("50+", Cesium.Color.RED, 48)
|
||||
.toDataURL();
|
||||
var pin40 = pinBuilder
|
||||
.fromText("40+", Cesium.Color.ORANGE, 48)
|
||||
.toDataURL();
|
||||
var pin30 = pinBuilder
|
||||
.fromText("30+", Cesium.Color.YELLOW, 48)
|
||||
.toDataURL();
|
||||
var pin20 = pinBuilder
|
||||
.fromText("20+", Cesium.Color.GREEN, 48)
|
||||
.toDataURL();
|
||||
var pin10 = pinBuilder
|
||||
.fromText("10+", Cesium.Color.BLUE, 48)
|
||||
.toDataURL();
|
||||
|
||||
var singleDigitPins = new Array(8);
|
||||
for (var i = 0; i < singleDigitPins.length; ++i) {
|
||||
singleDigitPins[i] = pinBuilder
|
||||
.fromText("" + (i + 2), Cesium.Color.VIOLET, 48)
|
||||
.toDataURL();
|
||||
}
|
||||
|
||||
function customStyle() {
|
||||
if (Cesium.defined(removeListener)) {
|
||||
removeListener();
|
||||
removeListener = undefined;
|
||||
} else {
|
||||
removeListener = dataSource.clustering.clusterEvent.addEventListener(
|
||||
function (clusteredEntities, cluster) {
|
||||
// cluster.label.show = false;
|
||||
// cluster.label.verticalOrigin = false;
|
||||
cluster.billboard.show = true;
|
||||
cluster.billboard.id = cluster.label.id;
|
||||
cluster.billboard.verticalOrigin =
|
||||
Cesium.VerticalOrigin.BOTTOM;
|
||||
// 根据聚合数量的多少设置不同层级的图片以及大小
|
||||
/*if (clusteredEntities.length >= 50) {
|
||||
cluster.billboard.image = that.combineIconAndLabel(host + '1_大红.png', clusteredEntities.length, 64);
|
||||
cluster.billboard.width = 72;
|
||||
cluster.billboard.height = 72;
|
||||
} else if (clusteredEntities.length >= 40) {
|
||||
cluster.billboard.image = that.combineIconAndLabel(host + '1_大黄.png', clusteredEntities.length, 64);
|
||||
cluster.billboard.width = 56;
|
||||
cluster.billboard.height = 56;
|
||||
} else if (clusteredEntities.length >= 30) {
|
||||
cluster.billboard.image = that.combineIconAndLabel(host + '1_大蓝.png', clusteredEntities.length, 64);
|
||||
cluster.billboard.width = 48;
|
||||
cluster.billboard.height = 48;
|
||||
} else if (clusteredEntities.length >= 20) {
|
||||
cluster.billboard.image = that.combineIconAndLabel(host + '1_小红.png', clusteredEntities.length, 64);
|
||||
cluster.billboard.width = 48;
|
||||
cluster.billboard.height = 48;
|
||||
} else if (clusteredEntities.length >= 10) {
|
||||
cluster.billboard.image = that.combineIconAndLabel(host + '1_小黄.png', clusteredEntities.length, 64);
|
||||
cluster.billboard.width = 48;
|
||||
cluster.billboard.height = 48;
|
||||
} else {
|
||||
cluster.billboard.image = that.combineIconAndLabel(host + '1_小蓝.png', clusteredEntities.length, 64);
|
||||
cluster.billboard.width = 40;
|
||||
cluster.billboard.height = 40;
|
||||
}*/
|
||||
|
||||
|
||||
cluster.billboard.image = tools.getSourceRootPath() + '/img/cluster.png'
|
||||
cluster.billboard.disableDepthTestDistance = getGroundCover() ? undefined : Number.POSITIVE_INFINITY
|
||||
|
||||
cluster.label.verticalOrigin = Cesium.VerticalOrigin.CENTER
|
||||
cluster.label.font = "18px Arial,sans-serif",
|
||||
// cluster.label.scale = 0.5
|
||||
cluster.label.disableDepthTestDistance = getGroundCover() ? undefined : Number.POSITIVE_INFINITY
|
||||
cluster.label.style = Cesium.LabelStyle.FILL
|
||||
cluster.label.showBackground = true
|
||||
cluster.label.backgroundColor = Cesium.Color.WHITE.withAlpha(0.0)
|
||||
|
||||
if (clusteredEntities.length >= 1000) {
|
||||
cluster.billboard.scale = 1.5;
|
||||
cluster.label.pixelOffset = new Cesium.Cartesian2(-28, -46)
|
||||
} else if (clusteredEntities.length >= 100) {
|
||||
cluster.billboard.scale = 1.25;
|
||||
cluster.label.pixelOffset = new Cesium.Cartesian2(-21, -40)
|
||||
} else if (clusteredEntities.length >= 50) {
|
||||
cluster.billboard.scale = 1.1;
|
||||
cluster.label.pixelOffset = new Cesium.Cartesian2(-16, -36)
|
||||
} else if (clusteredEntities.length >= 40) {
|
||||
cluster.billboard.scale = 1.05;
|
||||
cluster.label.pixelOffset = new Cesium.Cartesian2(-16, -34)
|
||||
} else if (clusteredEntities.length >= 30) {
|
||||
cluster.billboard.scale = 1;
|
||||
cluster.label.pixelOffset = new Cesium.Cartesian2(-16, -32)
|
||||
} else if (clusteredEntities.length >= 20) {
|
||||
cluster.billboard.scale = 0.95;
|
||||
cluster.label.pixelOffset = new Cesium.Cartesian2(-16, -30)
|
||||
} else if (clusteredEntities.length >= 10) {
|
||||
cluster.billboard.scale = 0.9;
|
||||
cluster.label.pixelOffset = new Cesium.Cartesian2(-16, -28)
|
||||
} else {
|
||||
cluster.billboard.scale = 0.8;
|
||||
cluster.label.pixelOffset = new Cesium.Cartesian2(-11, -25)
|
||||
}
|
||||
|
||||
// if (clusteredEntities.length >= 50) {
|
||||
// cluster.billboard.image = pin50;
|
||||
// } else if (clusteredEntities.length >= 40) {
|
||||
// cluster.billboard.image = pin40;
|
||||
// } else if (clusteredEntities.length >= 30) {
|
||||
// cluster.billboard.image = pin30;
|
||||
// } else if (clusteredEntities.length >= 20) {
|
||||
// cluster.billboard.image = pin20;
|
||||
// } else if (clusteredEntities.length >= 10) {
|
||||
// cluster.billboard.image = pin10;
|
||||
// } else {
|
||||
// cluster.billboard.image =
|
||||
// singleDigitPins[clusteredEntities.length - 2];
|
||||
// }
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// force a re-cluster with the new styling
|
||||
var pixelRange = dataSource.clustering.pixelRange;
|
||||
dataSource.clustering.pixelRange = 0;
|
||||
dataSource.clustering.pixelRange = pixelRange;
|
||||
}
|
||||
|
||||
// start with custom style
|
||||
customStyle();
|
||||
|
||||
var viewModel = {
|
||||
pixelRange: pixelRange,
|
||||
minimumClusterSize: minimumClusterSize,
|
||||
};
|
||||
Cesium.knockout.track(viewModel);
|
||||
|
||||
|
||||
function subscribeParameter(name) {
|
||||
Cesium.knockout
|
||||
.getObservable(viewModel, name)
|
||||
.subscribe(function (newValue) {
|
||||
dataSource.clustering[name] = newValue;
|
||||
});
|
||||
}
|
||||
|
||||
subscribeParameter("pixelRange");
|
||||
subscribeParameter("minimumClusterSize");
|
||||
// var handler = new Cesium.ScreenSpaceEventHandler(this.sdk.viewer.scene.canvas);
|
||||
// handler.setInputAction((movement) => {
|
||||
// var pickedLabel = this.sdk.viewer.scene.pick(movement.position);
|
||||
//
|
||||
// if (Cesium.defined(pickedLabel)) {
|
||||
// this.log(pickedLabel)
|
||||
// var ids = pickedLabel.id;
|
||||
// if (Array.isArray(ids)) {
|
||||
// for (var i = 0; i < ids.length; ++i) {
|
||||
// ids[i].billboard.color = Cesium.Color.RED;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 开启/关闭聚合效果
|
||||
* @method set_cluster_status
|
||||
* @param [enable=false] {boolean}默认关闭
|
||||
* @memberOf Tool-3D
|
||||
* */
|
||||
function switchCluster(sdk, enable = false) {
|
||||
let viewer = sdk.viewer
|
||||
for (let i = 0; i < viewer.dataSources._dataSources.length; i++) {
|
||||
if (viewer.dataSources._dataSources[i].name === "sdk-dataSource1") {
|
||||
viewer.dataSources._dataSources[i].clustering.enabled = enable
|
||||
// syncDataSources(viewer.dataSources._dataSources[i], 'clustering')
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addCluster(sdk, entity) {
|
||||
let viewer = sdk.viewer
|
||||
if(!viewer) {
|
||||
return
|
||||
}
|
||||
for (let i = 0; i < viewer.dataSources._dataSources.length; i++) {
|
||||
if (viewer.dataSources._dataSources[i].name === "sdk-dataSource1") {
|
||||
viewer.dataSources._dataSources[i].entities.add(entity)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function remove_entity_from_cluster(viewer, entity) {
|
||||
for (let i = 0; i < viewer.dataSources._dataSources.length; i++) {
|
||||
if (viewer.dataSources._dataSources[i].name === "sdk-dataSource1") {
|
||||
viewer.dataSources._dataSources[i].entities.remove(entity)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updateCluster(viewer) {
|
||||
if(!viewer) {
|
||||
return
|
||||
}
|
||||
for (let i = 0; i < viewer.dataSources._dataSources.length; i++) {
|
||||
if (viewer.dataSources._dataSources[i].name === "sdk-dataSource1") {
|
||||
viewer.dataSources._dataSources[i].clustering._cluster()
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export { createCluster, addCluster, switchCluster, remove_entity_from_cluster, updateCluster }
|
||||
159
src/Global/efflect/index.js
Normal file
159
src/Global/efflect/index.js
Normal file
@ -0,0 +1,159 @@
|
||||
/*全局特效*/
|
||||
|
||||
let rainStages = null;
|
||||
let snowStages = null;
|
||||
let fogStages = null;
|
||||
let nightVisionStages = null;
|
||||
|
||||
// 雨
|
||||
const FS_Rain = `uniform sampler2D colorTexture;//输入的场景渲染照片
|
||||
varying vec2 v_textureCoordinates;
|
||||
uniform float tiltAngle;
|
||||
uniform float rainSize;
|
||||
uniform float rainWidth;
|
||||
uniform float rainSpeed;
|
||||
|
||||
float hash(float x){
|
||||
return fract(sin(x*133.3)*13.13);
|
||||
}
|
||||
void main(void){
|
||||
float time = czm_frameNumber / rainSpeed;
|
||||
vec2 resolution = czm_viewport.zw;
|
||||
vec2 uv=(gl_FragCoord.xy*2.-resolution.xy)/min(resolution.x,resolution.y);
|
||||
vec3 c=vec3(.6,.7,.8);
|
||||
float a= tiltAngle;
|
||||
float si=sin(a),co=cos(a);
|
||||
uv*=mat2(co,-si,si,co);
|
||||
uv*=length(uv+vec2(0,4.9))*rainSize+1.;
|
||||
float v=1.-sin(hash(floor(uv.x*rainWidth))*2.);
|
||||
float b=clamp(abs(sin(20.*time*v+uv.y*(5./(2.+v))))-.95,0.,1.)*20.;
|
||||
c*=v*b; //屏幕上雨的颜色
|
||||
gl_FragColor = mix(texture2D(colorTexture, v_textureCoordinates), vec4(c,1), 0.5); //将雨和三维场景融合
|
||||
}`
|
||||
|
||||
// 雪
|
||||
const FS_Snow = `uniform sampler2D colorTexture;
|
||||
varying vec2 v_textureCoordinates;
|
||||
uniform float snowSize;
|
||||
uniform float snowSpeed;
|
||||
|
||||
float snow(vec2 uv,float scale)
|
||||
{
|
||||
float time = czm_frameNumber / snowSpeed;
|
||||
float w=smoothstep(1.,0.,-uv.y*(scale/10.));if(w<.1)return 0.;
|
||||
uv+=time/scale;uv.y+=time*2./scale;uv.x+=sin(uv.y+time*.5)/scale;
|
||||
uv*=scale;vec2 s=floor(uv),f=fract(uv),p;float k=3.,d;
|
||||
p=.5+.35*sin(11.*fract(sin((s+p+scale)*mat2(7,3,6,5))*5.))-f;d=length(p);k=min(d,k);
|
||||
k=smoothstep(0.,k,sin(f.x+f.y)*0.01*snowSize);
|
||||
return k*w;
|
||||
}
|
||||
void main(void){
|
||||
vec2 resolution = czm_viewport.zw;
|
||||
vec2 uv=(gl_FragCoord.xy*2.-resolution.xy)/min(resolution.x,resolution.y);
|
||||
vec3 finalColor=vec3(0);
|
||||
//float c=smoothstep(1.,0.3,clamp(uv.y*.3+.8,0.,.75));
|
||||
float c = 0.0;
|
||||
c+=snow(uv,30.)*.0;
|
||||
c+=snow(uv,20.)*.0;
|
||||
c+=snow(uv,15.)*.0;
|
||||
c+=snow(uv,10.);
|
||||
c+=snow(uv,8.);
|
||||
c+=snow(uv,6.);
|
||||
c+=snow(uv,5.);
|
||||
finalColor=(vec3(c));
|
||||
gl_FragColor = mix(texture2D(colorTexture, v_textureCoordinates), vec4(finalColor,1), 0.5);
|
||||
}
|
||||
`;
|
||||
|
||||
// 雾
|
||||
const FS_Fog = `
|
||||
uniform sampler2D colorTexture;
|
||||
uniform sampler2D depthTexture;
|
||||
uniform float visibility;
|
||||
uniform vec4 fogColor;
|
||||
varying vec2 v_textureCoordinates;
|
||||
void main(void)
|
||||
{
|
||||
vec4 origcolor = texture2D(colorTexture, v_textureCoordinates);
|
||||
float depth = czm_readDepth(depthTexture, v_textureCoordinates);
|
||||
vec4 depthcolor = texture2D(depthTexture, v_textureCoordinates);
|
||||
float f = visibility * (depthcolor.r - 0.3) / 0.2;
|
||||
if (f < 0.0) f = 0.0;
|
||||
else if (f > 1.0) f = 1.0;
|
||||
gl_FragColor = mix(origcolor, fogColor, f);
|
||||
}
|
||||
`;
|
||||
|
||||
|
||||
/*雨天*/
|
||||
function rain(sdk, status = false) {
|
||||
rainStages && sdk.viewer.scene.postProcessStages.remove(rainStages)
|
||||
if (status) {
|
||||
rainStages = new Cesium.PostProcessStage({
|
||||
name: "rain",
|
||||
fragmentShader: FS_Rain,
|
||||
uniforms: {
|
||||
tiltAngle: -0.4, // 倾斜角度
|
||||
rainSize: 0.3, // 雨大小
|
||||
rainWidth: 40, //雨长度
|
||||
rainSpeed: 100, //雨速
|
||||
},
|
||||
});
|
||||
sdk.viewer.scene.postProcessStages.add(rainStages);
|
||||
}
|
||||
}
|
||||
|
||||
// 雪
|
||||
function snow(sdk, status = false) {
|
||||
snowStages && sdk.viewer.scene.postProcessStages.remove(snowStages)
|
||||
if (status) {
|
||||
snowStages = new Cesium.PostProcessStage({
|
||||
name: "snow",
|
||||
fragmentShader: FS_Snow,
|
||||
uniforms: {
|
||||
snowSize: 2, // 大小
|
||||
snowSpeed: 60, //速度
|
||||
},
|
||||
});
|
||||
sdk.viewer.scene.postProcessStages.add(snowStages);
|
||||
}
|
||||
}
|
||||
|
||||
// 雾天
|
||||
function fog(sdk, status = false) {
|
||||
fogStages && sdk.viewer.scene.postProcessStages.remove(fogStages)
|
||||
if (status) {
|
||||
fogStages = new Cesium.PostProcessStage({
|
||||
name: "fog",
|
||||
fragmentShader: FS_Fog,
|
||||
uniforms: {
|
||||
visibility: 0.2, //
|
||||
fogColor: Cesium.Color.WHITE,
|
||||
},
|
||||
});
|
||||
sdk.viewer.scene.postProcessStages.add(fogStages);
|
||||
}
|
||||
}
|
||||
|
||||
// 夜视
|
||||
function nightVision(sdk, status = false) {
|
||||
nightVisionStages && sdk.viewer.scene.postProcessStages.remove(nightVisionStages)
|
||||
if (status) {
|
||||
nightVisionStages = Cesium.PostProcessStageLibrary.createNightVisionStage();
|
||||
sdk.viewer.scene.postProcessStages.add(nightVisionStages);
|
||||
}
|
||||
}
|
||||
|
||||
// 星空
|
||||
function skyStarry(sdk, status = false) {
|
||||
sdk.viewer.scene.skyAtmosphere.show = !status
|
||||
}
|
||||
|
||||
// 光照
|
||||
function illumination(sdk, status = false) {
|
||||
sdk.viewer.shadows = status
|
||||
sdk.viewer._shadows = status
|
||||
}
|
||||
|
||||
|
||||
export { rain, snow, fog, nightVision, skyStarry, illumination }
|
||||
825
src/Global/global.js
Normal file
825
src/Global/global.js
Normal file
@ -0,0 +1,825 @@
|
||||
/**
|
||||
* @name: global
|
||||
* @author: Administrator
|
||||
* @date: 2023-12-01 14:15
|
||||
* @description:global
|
||||
* @update: 2023-12-01 14:15
|
||||
*/
|
||||
|
||||
/*获取当前视角*/
|
||||
import MouseEvent from '../Event/index'
|
||||
import Tools from "../Tools";
|
||||
import { Proj } from "../Tools/proj";
|
||||
import { getTheme, setTheme } from "../Obj/Element/theme";
|
||||
import { setActiveViewer as setMultiViewportActiveViewer } from './MultiViewportMode'
|
||||
import { setActiveViewer as setSplitActiveViewer, getSdk } from './SplitScreen'
|
||||
import { updateCluster } from './cluster/cluster'
|
||||
|
||||
let coordinateSystem = 'EPSG:4326'
|
||||
let _cartesian
|
||||
let GroundCover = false
|
||||
let bimPickObject = {}
|
||||
let containerObject = {}
|
||||
let rotateAroundObject = {}
|
||||
function getCurrentView(sdk) {
|
||||
let tools = new Tools()
|
||||
let viewer = sdk.viewer
|
||||
return JSON.parse(JSON.stringify({
|
||||
// heading: viewer.camera.heading,
|
||||
// pitch: viewer.camera.pitch,
|
||||
// roll: viewer.camera.roll,
|
||||
position: tools.cartesian3Towgs84(viewer.camera.position, viewer),
|
||||
orientation: {
|
||||
heading: Cesium.Math.toDegrees(viewer.camera.heading),
|
||||
pitch: Cesium.Math.toDegrees(viewer.camera.pitch),
|
||||
roll: Cesium.Math.toDegrees(viewer.camera.roll)
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
/*设置默认视角*/
|
||||
function setDefaultView(sdk, options) {
|
||||
let viewer = sdk.viewer
|
||||
if (options) {
|
||||
viewer.CAMERA_DEFAULT_VIEW_RECTANGLE = {
|
||||
destination: options.destination || {},
|
||||
orientation: options.orientation || {}
|
||||
}
|
||||
}
|
||||
else {
|
||||
viewer.CAMERA_DEFAULT_VIEW_RECTANGLE = undefined
|
||||
//设置cesium的默认视角
|
||||
Cesium.Camera.DEFAULT_VIEW_RECTANGLE = Cesium.Rectangle.fromDegrees(
|
||||
//西边的经度
|
||||
89.5,
|
||||
//南边的纬度
|
||||
10.4,
|
||||
//东边的经度
|
||||
110.4,
|
||||
//北边的维度
|
||||
61.2
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/*定位到指定视角*/
|
||||
async function flyTo(sdk, options, duration = 3) {
|
||||
let tools = new Tools(sdk)
|
||||
let destination
|
||||
let orientation = options.orientation
|
||||
if (options.position) {
|
||||
if (options.position.alt !== 0 && !options.position.alt) {
|
||||
options.position.alt = await tools.getClampToHeight(options.position)
|
||||
}
|
||||
let h = 0
|
||||
if (!orientation) {
|
||||
h = 500
|
||||
}
|
||||
destination = Cesium.Cartesian3.fromDegrees(options.position.lng, options.position.lat, options.position.alt + h)
|
||||
}
|
||||
else {
|
||||
let bbox = tools.cal_envelope(options.positions)
|
||||
destination = new Cesium.Rectangle(
|
||||
Cesium.Math.toRadians(bbox[3][0]),
|
||||
Cesium.Math.toRadians(bbox[3][1]),
|
||||
Cesium.Math.toRadians(bbox[1][0]),
|
||||
Cesium.Math.toRadians(bbox[1][1])
|
||||
)
|
||||
}
|
||||
closeRotateAround(sdk)
|
||||
sdk.viewer.camera.flyTo({ destination, duration, orientation, complete: options.complete, })
|
||||
}
|
||||
|
||||
/*相机锁定*/
|
||||
function CameraController(sdk, status = true) {
|
||||
if (!sdk || !sdk.viewer) {
|
||||
return
|
||||
}
|
||||
let viewer = sdk.viewer
|
||||
viewer.scene.screenSpaceCameraController.enableRotate = status;
|
||||
viewer.scene.screenSpaceCameraController.enableTranslate = status;
|
||||
viewer.scene.screenSpaceCameraController.enableZoom = status;
|
||||
viewer.scene.screenSpaceCameraController.enableTilt = status;
|
||||
viewer.scene.screenSpaceCameraController.enableLook = status;
|
||||
}
|
||||
|
||||
/*控件显隐*/
|
||||
function CesiumContainer(sdk, options) {
|
||||
if (!sdk || !sdk.viewer) {
|
||||
return
|
||||
}
|
||||
containerObject[sdk.viewer._element.className] || (containerObject[sdk.viewer._element.className] = {})
|
||||
containerObject[sdk.viewer._element.className].event && containerObject[sdk.viewer._element.className].event.destroy()
|
||||
let tools = new Tools()
|
||||
let element = sdk.viewer._element
|
||||
let proj = sdk.proj
|
||||
for (let key in options) {
|
||||
switch (key) {
|
||||
case 'compass':
|
||||
let compass = element.getElementsByClassName('compass')[0]
|
||||
let navigation = element.getElementsByClassName('navigation-controls')[0]
|
||||
if (options[key]) {
|
||||
compass && (compass.style.display = 'block')
|
||||
navigation && (navigation.style.display = 'flex')
|
||||
}
|
||||
else {
|
||||
compass && (compass.style.display = 'none')
|
||||
navigation && (navigation.style.display = 'none')
|
||||
}
|
||||
break;
|
||||
case 'legend':
|
||||
let distanceLegend = element.getElementsByClassName('distance-legend')[0]
|
||||
if (options[key]) {
|
||||
distanceLegend && (distanceLegend.parentNode.style.display = 'block')
|
||||
}
|
||||
else {
|
||||
distanceLegend && (distanceLegend.parentNode.style.display = 'none')
|
||||
}
|
||||
break;
|
||||
case 'info':
|
||||
let infoElm = element.getElementsByClassName('cesium-info')[0]
|
||||
if (options[key]) {
|
||||
if (infoElm) {
|
||||
update()
|
||||
infoElm.style.display = 'block'
|
||||
}
|
||||
else {
|
||||
infoElm = document.createElement('div');
|
||||
infoElm.className = "cesium-info"
|
||||
infoElm.style.position = 'absolute';
|
||||
infoElm.style.bottom = '32px';
|
||||
infoElm.style.right = '240px';
|
||||
infoElm.style['font-size'] = '14px';
|
||||
infoElm.style['background-color'] = 'rgba(47,53,60,.8)';
|
||||
infoElm.style.color = '#fff';
|
||||
infoElm.style.padding = '4px 10px';
|
||||
infoElm.style['border-radius'] = '18px';
|
||||
|
||||
if (coordinateSystem === 'EPSG:4326') {
|
||||
infoElm.innerHTML = `
|
||||
<span>经度:</span><span>-</span>
|
||||
<span>纬度:</span><span>-</span>
|
||||
<span>海拔高度:</span><span>-</span>
|
||||
`
|
||||
}
|
||||
else {
|
||||
infoElm.innerHTML = `
|
||||
<span>x:</span><span>-</span>
|
||||
<span>y:</span><span>-</span>
|
||||
<span>z:</span><span>-</span>
|
||||
`
|
||||
}
|
||||
sdk.viewer._element.appendChild(infoElm)
|
||||
}
|
||||
let event = new MouseEvent(sdk)
|
||||
containerObject[sdk.viewer._element.className].event = event
|
||||
event.mouse_move((movement, cartesian) => {
|
||||
_cartesian = cartesian
|
||||
update()
|
||||
})
|
||||
function update() {
|
||||
if (!_cartesian) {
|
||||
return
|
||||
}
|
||||
let position = tools.cartesian3Towgs84(_cartesian, sdk.viewer)
|
||||
if (coordinateSystem === 'EPSG:4326') {
|
||||
infoElm.innerHTML = `
|
||||
<span>经度:</span><span>${Number(position.lng.toFixed(6))}° </span>
|
||||
<span>纬度:</span><span>${Number(position.lat.toFixed(6))}° </span>
|
||||
<span>海拔高度:</span><span>${Number(position.alt.toFixed(2))}米</span>
|
||||
`
|
||||
}
|
||||
else {
|
||||
let result = proj.convert([{ x: position.lng, y: position.lat, z: position.alt }], 'EPSG:4326', coordinateSystem)
|
||||
infoElm.innerHTML = `
|
||||
<span>x:</span><span>${Number(result.points[0].x.toFixed(6))}</span>
|
||||
<span style="margin-left: 5px;">y:</span><span>${Number(result.points[0].y.toFixed(6))}</span>
|
||||
<span style="margin-left: 5px;">z:</span><span>${Number(result.points[0].z.toFixed(6))}</span>
|
||||
`
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
infoElm && (infoElm.style.display = 'none')
|
||||
}
|
||||
break;
|
||||
case 'frame':
|
||||
if (options[key]) {
|
||||
sdk.viewer.scene.debugShowFramesPerSecond = true;
|
||||
setTimeout(() => {
|
||||
let cesiumWidgetContainerElm = sdk.viewer._element.getElementsByClassName('cesium-viewer-cesiumWidgetContainer')[0]
|
||||
let defaultContainer = cesiumWidgetContainerElm.getElementsByClassName('cesium-performanceDisplay-defaultContainer')[0]
|
||||
if (defaultContainer) {
|
||||
cesiumWidgetContainerElm.appendChild(defaultContainer)
|
||||
}
|
||||
}, 50);
|
||||
}
|
||||
else {
|
||||
sdk.viewer.scene.debugShowFramesPerSecond = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// let compass = element.getElementsByClassName('compass')[0]
|
||||
// let navigation = element.getElementsByClassName('navigation-controls')[0]
|
||||
// let distanceLegend = element.getElementsByClassName('distance-legend')[0]
|
||||
// if(status) {
|
||||
// compass && (compass.style.display = 'block')
|
||||
// navigation && (navigation.style.display = 'block')
|
||||
// distanceLegend && (distanceLegend.style.display = 'block')
|
||||
// }
|
||||
// else {
|
||||
// compass && (compass.style.display = 'none')
|
||||
// navigation && (navigation.style.display = 'none')
|
||||
// distanceLegend && (distanceLegend.style.display = 'none')
|
||||
// viewer.cesiumNavigation.distanceLegendViewModel.destroy()
|
||||
// }
|
||||
}
|
||||
|
||||
/*设置广告牌默认图标*/
|
||||
function setBillboardDefaultUrl(url, name) {
|
||||
if (name) {
|
||||
name = 'billboard_default_url_' + name
|
||||
}
|
||||
else {
|
||||
name = 'billboard_default_url'
|
||||
}
|
||||
localStorage.setItem(name, url);
|
||||
}
|
||||
/*获取广告牌默认图标*/
|
||||
function getBillboardDefaultUrl(name) {
|
||||
if (name) {
|
||||
name = 'billboard_default_url_' + name
|
||||
}
|
||||
else {
|
||||
name = 'billboard_default_url'
|
||||
}
|
||||
return localStorage.getItem(name);
|
||||
}
|
||||
|
||||
/*设置高度参考*/
|
||||
function setGroundCover(sdk, status) {
|
||||
GroundCover = status ? true : false
|
||||
updateCluster(sdk.viewer)
|
||||
}
|
||||
|
||||
/*获取高度参考*/
|
||||
function getGroundCover() {
|
||||
return GroundCover
|
||||
}
|
||||
|
||||
function setBimPickStatus(sdk, status) {
|
||||
if (!sdk || !sdk.viewer) {
|
||||
return
|
||||
}
|
||||
bimPickObject[sdk.viewer._element.className] || (bimPickObject[sdk.viewer._element.className] = {})
|
||||
bimPickObject[sdk.viewer._element.className].status = status
|
||||
if (bimPickObject[sdk.viewer._element.className].MoveHandler) {
|
||||
bimPickObject[sdk.viewer._element.className].MoveHandler.destroy()
|
||||
}
|
||||
if (!status) {
|
||||
return
|
||||
}
|
||||
bimPickObject[sdk.viewer._element.className].MoveHandler = new Cesium.ScreenSpaceEventHandler(sdk.viewer.canvas)
|
||||
bimPickObject[sdk.viewer._element.className].MoveHandler.setInputAction(function (movement) {
|
||||
const pick = sdk.viewer.scene.pick(movement.endPosition);
|
||||
let selectedId = bimPickObject[sdk.viewer._element.className].selectedId
|
||||
let that = sdk.entityMap.get(bimPickObject[sdk.viewer._element.className].id)
|
||||
// if (selectedFeatureId) {
|
||||
// let color = '#fff'
|
||||
// let state = selectedFeature.getProperty('state')
|
||||
// switch (state) {
|
||||
// case '0':
|
||||
// color = '#fff'
|
||||
// break;
|
||||
// case '1':
|
||||
// color = '#f00'
|
||||
// break;
|
||||
// case '2':
|
||||
// color = '#0f0'
|
||||
// break;
|
||||
// case '3':
|
||||
// color = '#00f'
|
||||
// break;
|
||||
// default:
|
||||
// }
|
||||
// selectedFeature.color = Cesium.Color.fromCssColorString(color).withAlpha(selectedFeature.tileset.transparency)
|
||||
// }
|
||||
if (that) {
|
||||
if (that.features.has(selectedId)) {
|
||||
let features = that.features.get(selectedId).features
|
||||
for (let key in features) {
|
||||
if (features[key].content._model) {
|
||||
let color = features[key].customColor || Cesium.Color.fromCssColorString('#fff')
|
||||
features[key].color = Cesium.Color.fromCssColorString(`rgba(${Cesium.Color.floatToByte(color.red)},${Cesium.Color.floatToByte(color.green)},${Cesium.Color.floatToByte(color.blue)},${color.alpha * ((features[key].customAlpha || features[key].customAlpha === 0) ? features[key].customAlpha : 1)})`)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pick && pick.content) {
|
||||
let obj = sdk.getIncetance(pick.content.tileset.id)
|
||||
if (obj.type === 'bim') {
|
||||
if (pick.primitive && pick.primitive.id) {
|
||||
let that = sdk.entityMap.get(pick.primitive.id)
|
||||
selectedId = pick.getProperty('id')
|
||||
if (that.features.has(selectedId)) {
|
||||
let features = that.features.get(selectedId).features
|
||||
for (let key in features) {
|
||||
if (features[key].content._model) {
|
||||
features[key].color = Cesium.Color.fromCssColorString('#ffeb3b')
|
||||
}
|
||||
}
|
||||
}
|
||||
bimPickObject[sdk.viewer._element.className].id = pick.primitive.id
|
||||
bimPickObject[sdk.viewer._element.className].selectedId = selectedId
|
||||
}
|
||||
}
|
||||
else {
|
||||
pick.primitive.id = null
|
||||
}
|
||||
}
|
||||
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
|
||||
}
|
||||
|
||||
function getBimPickStatus(sdk) {
|
||||
if (!sdk || !sdk.viewer) {
|
||||
return
|
||||
}
|
||||
return bimPickObject[sdk.viewer._element.className] ? bimPickObject[sdk.viewer._element.className].status : false
|
||||
}
|
||||
|
||||
/* 围绕坐标旋转 */
|
||||
function rotateAround(sdk, position) {
|
||||
if (!sdk || !sdk.viewer) {
|
||||
return
|
||||
}
|
||||
setActiveViewer(0)
|
||||
sdk.viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
|
||||
// 关闭Controller
|
||||
sdk.entityMap.forEach((item) => {
|
||||
item.editObj && item.editObj.destroy()
|
||||
item.ControllerObject && item.ControllerObject.destroy()
|
||||
})
|
||||
rotateAroundObject[sdk.viewer._element.className] || (rotateAroundObject[sdk.viewer._element.className] = {})
|
||||
rotateAroundObject[sdk.viewer._element.className].animate && TWEEN.remove(rotateAroundObject[sdk.viewer._element.className].animate)
|
||||
rotateAroundObject[sdk.viewer._element.className].event && rotateAroundObject[sdk.viewer._element.className].event.destroy()
|
||||
if (!position) {
|
||||
CameraController(sdk, true)
|
||||
return
|
||||
}
|
||||
|
||||
let point = Cesium.Cartesian3.fromDegrees(position.lng, position.lat, position.alt)
|
||||
let angle = Cesium.Math.toDegrees(sdk.viewer.camera.heading)
|
||||
let range = Cesium.Cartesian3.distance(sdk.viewer.camera.position, point);
|
||||
CameraController(sdk, false)
|
||||
let pitch = sdk.viewer.camera.pitch
|
||||
let degrees = Cesium.Math.toDegrees(pitch)
|
||||
if (degrees < -89.99) {
|
||||
pitch = Cesium.Math.toRadians(-89.99)
|
||||
}
|
||||
rotateAroundObject[sdk.viewer._element.className].animate = new TWEEN.Tween({ angle: angle }).to({ angle: angle - 360 }, 30000).easing(TWEEN.Easing.Linear.None).repeat(Infinity).onUpdate(async (r, a) => {
|
||||
if (!sdk.viewer) {
|
||||
TWEEN.remove(rotateAroundObject[sdk.viewer._element.className].animate)
|
||||
return
|
||||
}
|
||||
sdk.viewer.camera.lookAt(
|
||||
point,
|
||||
new Cesium.HeadingPitchRange(Cesium.Math.toRadians(r.angle), pitch, range)
|
||||
)
|
||||
|
||||
sdk.viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
|
||||
}).start()
|
||||
|
||||
let event = new MouseEvent(sdk)
|
||||
rotateAroundObject[sdk.viewer._element.className].event = event
|
||||
event.mouse_left_down(() => {
|
||||
rotateAroundObject[sdk.viewer._element.className].animate && TWEEN.remove(rotateAroundObject[sdk.viewer._element.className].animate)
|
||||
rotateAroundObject[sdk.viewer._element.className].event && rotateAroundObject[sdk.viewer._element.className].event.destroy()
|
||||
CameraController(sdk, true)
|
||||
sdk.viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
|
||||
})
|
||||
}
|
||||
|
||||
/* 关闭围绕坐标旋转 */
|
||||
function closeRotateAround(sdk) {
|
||||
if (!sdk || !sdk.viewer) {
|
||||
return
|
||||
}
|
||||
if (rotateAroundObject[sdk.viewer._element.className]) {
|
||||
rotateAroundObject[sdk.viewer._element.className].animate && TWEEN.remove(rotateAroundObject[sdk.viewer._element.className].animate)
|
||||
rotateAroundObject[sdk.viewer._element.className].event && rotateAroundObject[sdk.viewer._element.className].event.destroy()
|
||||
CameraController(sdk, true)
|
||||
sdk.viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
|
||||
}
|
||||
}
|
||||
|
||||
function closeViewFollow(sdk) {
|
||||
if (sdk && sdk.entityMap) {
|
||||
let entityMap = sdk.entityMap
|
||||
for (let [key, value] of entityMap) {
|
||||
if (value.type === 'TrajectoryMotion' && value.viewFollow) {
|
||||
value.viewFollow = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 方里网状态开关 */
|
||||
function FlwStatusSwitch(sdk, status) {
|
||||
if(!sdk) {
|
||||
return
|
||||
}
|
||||
let layer
|
||||
let sdkD = getSdk().sdkD
|
||||
if(sdkD && sdk !== sdkD) {
|
||||
FlwStatusSwitch(sdkD, status)
|
||||
}
|
||||
for (let i = 0; i < sdk.viewer.imageryLayers._layers.length; i++) {
|
||||
if (sdk.viewer.imageryLayers._layers[i]._imageryProvider && sdk.viewer.imageryLayers._layers[i]._imageryProvider._type && sdk.viewer.imageryLayers._layers[i]._imageryProvider._type === 'flw') {
|
||||
layer = sdk.viewer.imageryLayers._layers[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
if (layer) {
|
||||
sdk.viewer.imageryLayers.remove(layer)
|
||||
}
|
||||
if (status) {
|
||||
sdk.viewer.imageryLayers.addImageryProvider(new Cesium.TileCoordinatesImageryProviderFlw(
|
||||
{
|
||||
tileWidth: 128,
|
||||
tileHeight: 128,
|
||||
}
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
function getFlwStatus(sdk) {
|
||||
let status = false
|
||||
for (let i = 0; i < sdk.viewer.imageryLayers._layers.length; i++) {
|
||||
if (sdk.viewer.imageryLayers._layers[i]._imageryProvider && sdk.viewer.imageryLayers._layers[i]._imageryProvider._type && sdk.viewer.imageryLayers._layers[i]._imageryProvider._type === 'flw') {
|
||||
status = true
|
||||
break
|
||||
}
|
||||
}
|
||||
return status
|
||||
}
|
||||
|
||||
/* 经纬网状态开关 */
|
||||
function JwwStatusSwitch(sdk, status) {
|
||||
if(!sdk) {
|
||||
return
|
||||
}
|
||||
let layer
|
||||
let sdkD = getSdk().sdkD
|
||||
if(sdkD && sdk !== sdkD) {
|
||||
JwwStatusSwitch(sdkD, status)
|
||||
}
|
||||
for (let i = 0; i < sdk.viewer.imageryLayers._layers.length; i++) {
|
||||
if (sdk.viewer.imageryLayers._layers[i]._imageryProvider && sdk.viewer.imageryLayers._layers[i]._imageryProvider._type && sdk.viewer.imageryLayers._layers[i]._imageryProvider._type === 'jww') {
|
||||
layer = sdk.viewer.imageryLayers._layers[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
if (layer) {
|
||||
sdk.viewer.imageryLayers.remove(layer)
|
||||
}
|
||||
if (status) {
|
||||
sdk.viewer.imageryLayers.addImageryProvider(new Cesium.TileCoordinatesImageryProviderJww());
|
||||
}
|
||||
}
|
||||
|
||||
function getJwwStatus(sdk) {
|
||||
let status = false
|
||||
for (let i = 0; i < sdk.viewer.imageryLayers._layers.length; i++) {
|
||||
if (sdk.viewer.imageryLayers._layers[i]._imageryProvider && sdk.viewer.imageryLayers._layers[i]._imageryProvider._type && sdk.viewer.imageryLayers._layers[i]._imageryProvider._type === 'jww') {
|
||||
status = true
|
||||
break
|
||||
}
|
||||
}
|
||||
return status
|
||||
}
|
||||
|
||||
function splitScreen2(sdk, status) {
|
||||
let sliderElm = sdk.viewer._element.getElementsByClassName('YJ-custom-slider')[0]
|
||||
let leftElm = sdk.viewer._element.getElementsByClassName('YJ-custom-checkbox-left')[0]
|
||||
let rightElm = sdk.viewer._element.getElementsByClassName('YJ-custom-checkbox-right')[0]
|
||||
if (sliderElm) {
|
||||
sdk.viewer._element.removeChild(sliderElm)
|
||||
sdk.viewer._element.removeChild(leftElm)
|
||||
sdk.viewer._element.removeChild(rightElm)
|
||||
}
|
||||
if (status) {
|
||||
sliderElm = document.createElement('div');
|
||||
sliderElm.className = 'YJ-custom-slider'
|
||||
sliderElm.style.position = 'absolute'
|
||||
sliderElm.style.left = '50%'
|
||||
sliderElm.style.top = '0px'
|
||||
|
||||
leftElm = document.createElement('input');
|
||||
leftElm.className = 'YJ-custom-checkbox-left'
|
||||
leftElm.type = 'checkbox'
|
||||
leftElm.style.position = 'absolute'
|
||||
leftElm.style.left = 'calc(50% - 50px)'
|
||||
rightElm = document.createElement('input');
|
||||
rightElm.className = 'YJ-custom-checkbox-right'
|
||||
rightElm.type = 'checkbox'
|
||||
rightElm.style.position = 'absolute'
|
||||
rightElm.style.right = 'calc(50% - 50px)'
|
||||
sdk.viewer._element.appendChild(leftElm)
|
||||
sdk.viewer._element.appendChild(rightElm)
|
||||
|
||||
leftElm.checked = true
|
||||
leftElm.addEventListener('change', (e) => {
|
||||
if (!e.target.checked) {
|
||||
if (!rightElm.checked) {
|
||||
rightElm.checked = true
|
||||
}
|
||||
}
|
||||
changeEntitySplitStatus()
|
||||
})
|
||||
rightElm.addEventListener('change', (e) => {
|
||||
if (!e.target.checked) {
|
||||
if (!leftElm.checked) {
|
||||
leftElm.checked = true
|
||||
}
|
||||
}
|
||||
changeEntitySplitStatus()
|
||||
})
|
||||
|
||||
sliderElm.addEventListener('mousedown', () => {
|
||||
document.body.addEventListener('mousemove', mousemove)
|
||||
sliderElm.addEventListener('mouseup', () => {
|
||||
document.body.removeEventListener('mousemove', mousemove)
|
||||
})
|
||||
})
|
||||
function mousemove(a, b) {
|
||||
if (sdk.viewer._element.getElementsByTagName('canvas')[0] === a.target) {
|
||||
sliderElm.style.left = (a.offsetX / sdk.viewer._element.scrollWidth * 100) + '%'
|
||||
sdk.viewer.scene.splitPosition = a.offsetX / sdk.viewer._element.scrollWidth
|
||||
}
|
||||
}
|
||||
sdk.viewer._element.appendChild(sliderElm)
|
||||
sdk.viewer.scene.splitStatus = status
|
||||
sdk.viewer.scene.splitPosition = 0.5
|
||||
changeEntitySplitStatus()
|
||||
}
|
||||
else {
|
||||
sdk.viewer.scene.splitPosition = 0
|
||||
changeEntitySplitStatus(0)
|
||||
sdk.viewer.scene.splitStatus = status
|
||||
}
|
||||
|
||||
function changeEntitySplitStatus(v) {
|
||||
let value
|
||||
if (v === undefined || v === null) {
|
||||
if (leftElm.checked && rightElm.checked) {
|
||||
value = 0
|
||||
}
|
||||
else {
|
||||
if (leftElm.checked) {
|
||||
value = -1
|
||||
}
|
||||
if (rightElm.checked) {
|
||||
value = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
value = v
|
||||
}
|
||||
|
||||
sdk.entityMap.forEach((item, key) => {
|
||||
if (sdk.viewer.scene.splitStatus) {
|
||||
if (item.entity.billboard) {
|
||||
item.entity.billboard.splitDirection = value
|
||||
}
|
||||
else {
|
||||
item.entity && (item.entity.splitDirection = value)
|
||||
}
|
||||
}
|
||||
console.log()
|
||||
})
|
||||
}
|
||||
}
|
||||
function splitScreen(sdk, status) {
|
||||
let sliderElm = sdk.viewer._element.getElementsByClassName('YJ-custom-slider')[0]
|
||||
let leftElm = sdk.viewer._element.getElementsByClassName('YJ-custom-checkbox-left')[0]
|
||||
let rightElm = sdk.viewer._element.getElementsByClassName('YJ-custom-checkbox-right')[0]
|
||||
if (sliderElm) {
|
||||
sdk.viewer._element.removeChild(sliderElm)
|
||||
sdk.viewer._element.removeChild(leftElm)
|
||||
sdk.viewer._element.removeChild(rightElm)
|
||||
}
|
||||
if (status) {
|
||||
sliderElm = document.createElement('div');
|
||||
sliderElm.className = 'YJ-custom-slider'
|
||||
sliderElm.style.position = 'absolute'
|
||||
sliderElm.style.left = '50%'
|
||||
sliderElm.style.top = '0px'
|
||||
|
||||
leftElm = document.createElement('input');
|
||||
leftElm.className = 'YJ-custom-checkbox-left'
|
||||
leftElm.type = 'checkbox'
|
||||
leftElm.style.position = 'absolute'
|
||||
leftElm.style.left = 'calc(50% - 50px)'
|
||||
rightElm = document.createElement('input');
|
||||
rightElm.className = 'YJ-custom-checkbox-right'
|
||||
rightElm.type = 'checkbox'
|
||||
rightElm.style.position = 'absolute'
|
||||
rightElm.style.right = 'calc(50% - 50px)'
|
||||
sdk.viewer._element.appendChild(leftElm)
|
||||
sdk.viewer._element.appendChild(rightElm)
|
||||
|
||||
leftElm.checked = true
|
||||
leftElm.addEventListener('change', (e) => {
|
||||
if (!e.target.checked) {
|
||||
if (!rightElm.checked) {
|
||||
rightElm.checked = true
|
||||
}
|
||||
}
|
||||
changeEntitySplitStatus()
|
||||
})
|
||||
rightElm.addEventListener('change', (e) => {
|
||||
if (!e.target.checked) {
|
||||
if (!leftElm.checked) {
|
||||
leftElm.checked = true
|
||||
}
|
||||
}
|
||||
changeEntitySplitStatus()
|
||||
})
|
||||
|
||||
sliderElm.addEventListener('mousedown', () => {
|
||||
document.body.addEventListener('mousemove', mousemove)
|
||||
sliderElm.addEventListener('mouseup', () => {
|
||||
document.body.removeEventListener('mousemove', mousemove)
|
||||
})
|
||||
})
|
||||
function mousemove(a, b) {
|
||||
if (sdk.viewer._element.getElementsByTagName('canvas')[0] === a.target) {
|
||||
sliderElm.style.left = (a.offsetX / sdk.viewer._element.scrollWidth * 100) + '%'
|
||||
sdk.viewer.scene.splitPosition = a.offsetX / sdk.viewer._element.scrollWidth
|
||||
}
|
||||
}
|
||||
sdk.viewer._element.appendChild(sliderElm)
|
||||
sdk.viewer.scene.splitStatus = status
|
||||
sdk.viewer.scene.splitPosition = 0.5
|
||||
changeEntitySplitStatus()
|
||||
}
|
||||
else {
|
||||
sdk.viewer.scene.splitPosition = 0
|
||||
changeEntitySplitStatus(0)
|
||||
sdk.viewer.scene.splitStatus = status
|
||||
}
|
||||
|
||||
function changeEntitySplitStatus(v) {
|
||||
let value
|
||||
if (v === undefined || v === null) {
|
||||
if (leftElm.checked && rightElm.checked) {
|
||||
value = 0
|
||||
}
|
||||
else {
|
||||
if (leftElm.checked) {
|
||||
value = -1
|
||||
}
|
||||
if (rightElm.checked) {
|
||||
value = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
value = v
|
||||
}
|
||||
|
||||
sdk.entityMap.forEach((item, key) => {
|
||||
if (sdk.viewer.scene.splitStatus) {
|
||||
if (item.entity.billboard) {
|
||||
item.entity.billboard.splitDirection = value
|
||||
}
|
||||
else {
|
||||
item.entity && (item.entity.splitDirection = value)
|
||||
}
|
||||
}
|
||||
console.log()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function getCoordinateSystem() {
|
||||
return coordinateSystem
|
||||
}
|
||||
|
||||
function setCoordinateSystem(sdk, epsg) {
|
||||
coordinateSystem = epsg || 'EPSG:4326'
|
||||
if (!sdk || !sdk.viewer || !sdk.viewer._element) {
|
||||
return
|
||||
}
|
||||
let infoElm = sdk.viewer._element.getElementsByClassName('cesium-info')[0]
|
||||
if (!_cartesian || !infoElm) {
|
||||
return
|
||||
}
|
||||
let tools = new Tools()
|
||||
let proj = sdk.proj
|
||||
let position = tools.cartesian3Towgs84(_cartesian, sdk.viewer)
|
||||
if (coordinateSystem === 'EPSG:4326') {
|
||||
infoElm.innerHTML = `
|
||||
<span>经度:</span><span>${Number(position.lng.toFixed(6))}° </span>
|
||||
<span>纬度:</span><span>${Number(position.lat.toFixed(6))}° </span>
|
||||
<span>海拔高度:</span><span>${Number(position.alt.toFixed(2))}米</span>
|
||||
`
|
||||
}
|
||||
else {
|
||||
let result = proj.convert([{ x: position.lng, y: position.lat, z: position.alt }], 'EPSG:4326', coordinateSystem)
|
||||
infoElm.innerHTML = `
|
||||
<span>x:</span><span>${Number(result.points[0].x.toFixed(6))}</span>
|
||||
<span style="margin-left: 5px;">y:</span><span>${Number(result.points[0].y.toFixed(6))}</span>
|
||||
<span style="margin-left: 5px;">z:</span><span>${Number(result.points[0].z.toFixed(6))}</span>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
function cameraChanged(sdk, cb) {
|
||||
let tools = new Tools()
|
||||
//设置相机变化的监听事件
|
||||
let removeChanged = sdk.viewer.camera.changed.addEventListener(percentage => {
|
||||
cb({
|
||||
position: tools.cartesian3Towgs84(sdk.viewer.camera.position, sdk.viewer),
|
||||
orientation: {
|
||||
heading: sdk.viewer.camera.heading,
|
||||
pitch: sdk.viewer.camera.pitch,
|
||||
roll: sdk.viewer.camera.roll
|
||||
}
|
||||
})
|
||||
})
|
||||
return removeChanged
|
||||
}
|
||||
|
||||
function setMaximumRequestsPerServer(v) {
|
||||
if (typeof v == 'number')
|
||||
Cesium.RequestScheduler.maximumRequestsPerServer = v
|
||||
}
|
||||
|
||||
/* 键盘事件 */
|
||||
function setKeyboardEventActive(sdk, status) {
|
||||
if (!sdk) {
|
||||
return
|
||||
}
|
||||
if (status) {
|
||||
sdk.viewer._disableKeyboardEvent = false
|
||||
}
|
||||
else {
|
||||
sdk.viewer._disableKeyboardEvent = true
|
||||
}
|
||||
}
|
||||
|
||||
function getCesiumIndexedDBMaxSize() {
|
||||
const baseUnit = 1024 * 1024 * 1024
|
||||
let size = Number(Number(localStorage.getItem('IndexedDBMaxSize')).toFixed(0))
|
||||
if (isNaN(size) || size < baseUnit) {
|
||||
size = baseUnit
|
||||
}
|
||||
return size
|
||||
}
|
||||
function setCesiumIndexedDBMaxSize(v) {
|
||||
const baseUnit = 1024 * 1024 * 1024
|
||||
let maxSize = Number(Number(v).toFixed(0))
|
||||
if (isNaN(maxSize) || maxSize < baseUnit) {
|
||||
maxSize = baseUnit
|
||||
}
|
||||
Cesium.ManageIndexedDB && Cesium.ManageIndexedDB.SetIndexedDBMaxSize(maxSize)
|
||||
localStorage.setItem('IndexedDBMaxSize', maxSize)
|
||||
}
|
||||
|
||||
function getCesiumManageIndexexDBState() {
|
||||
let state = localStorage.getItem('ManageIndexexDBState')
|
||||
if (state === 'false') {
|
||||
return false
|
||||
}
|
||||
return Boolean(state)
|
||||
}
|
||||
function setCesiumManageIndexexDBState(v) {
|
||||
if (typeof v === "boolean") {
|
||||
Cesium.ManageIndexedDB && Cesium.ManageIndexedDB.SetManageIndexexDBState(v)
|
||||
localStorage.setItem('ManageIndexexDBState', v)
|
||||
} else {
|
||||
console.error("参数必须为boolean")
|
||||
}
|
||||
}
|
||||
|
||||
function getCesiumIndexedDBCurrentSize() {
|
||||
return Cesium.ManageIndexedDB && Cesium.ManageIndexedDB.GetIndexedDBCurrentSize()
|
||||
}
|
||||
|
||||
function setActiveViewer(v) {
|
||||
setMultiViewportActiveViewer(v)
|
||||
setSplitActiveViewer(v)
|
||||
}
|
||||
|
||||
// 设置地球透明度
|
||||
function enablePerspective(sdk, alpha = 1) {
|
||||
if (!alpha && alpha != 0) {
|
||||
alpha = 1
|
||||
}
|
||||
sdk.viewer.scene.globe.translucency.frontFaceAlpha = alpha
|
||||
}
|
||||
|
||||
export { getCurrentView, setDefaultView, flyTo, CameraController, CesiumContainer, setBillboardDefaultUrl, getBillboardDefaultUrl, setGroundCover, getGroundCover, getBimPickStatus, setBimPickStatus, rotateAround, closeRotateAround, closeViewFollow, FlwStatusSwitch, JwwStatusSwitch, getFlwStatus, getJwwStatus, getCoordinateSystem, setCoordinateSystem, cameraChanged, setMaximumRequestsPerServer, setKeyboardEventActive, getTheme, setTheme, getCesiumIndexedDBMaxSize, setCesiumIndexedDBMaxSize, getCesiumManageIndexexDBState, setCesiumManageIndexexDBState, getCesiumIndexedDBCurrentSize, setActiveViewer, enablePerspective }
|
||||
218
src/Global/mouseRightMenu/index.js
Normal file
218
src/Global/mouseRightMenu/index.js
Normal file
@ -0,0 +1,218 @@
|
||||
/* 右键点击菜单 */
|
||||
import MouseEvent from '../../Event/index'
|
||||
import Tools from '../../Tools'
|
||||
import { rotateAround } from '../../Global/global'
|
||||
import { getSdk } from '../SplitScreen'
|
||||
|
||||
let eventListener = {}
|
||||
|
||||
function MouseRightMenu(sdk, status, callBack) {
|
||||
if (!sdk || !sdk.div_id) {
|
||||
return
|
||||
}
|
||||
let sdkD = getSdk().sdkD
|
||||
let _element = document.getElementById(sdk.div_id).getElementsByClassName('cesium-viewer')[0]
|
||||
let tools = new Tools()
|
||||
if (!eventListener[sdk.div_id]) {
|
||||
eventListener[sdk.div_id] = {}
|
||||
}
|
||||
if (eventListener[sdk.div_id].mousedown) {
|
||||
document.removeEventListener(
|
||||
'mousedown',
|
||||
eventListener[sdk.div_id].mousedown
|
||||
)
|
||||
}
|
||||
if (eventListener[sdk.div_id].click) {
|
||||
document.removeEventListener('click', eventListener[sdk.div_id].click)
|
||||
}
|
||||
if(!eventListener[sdk.div_id].callBack) {
|
||||
eventListener[sdk.div_id].callBack = callBack
|
||||
}
|
||||
|
||||
if(sdk !== sdkD) {
|
||||
eventListener[sdk.div_id].mouseRightMenuEvent &&
|
||||
eventListener[sdk.div_id].mouseRightMenuEvent.destroy()
|
||||
}
|
||||
|
||||
let menuElm = document.getElementById('custom-menu')
|
||||
if (menuElm) {
|
||||
_element.removeChild(menuElm)
|
||||
}
|
||||
eventListener[sdk.div_id].status = status
|
||||
if (status) {
|
||||
eventListener[sdk.div_id].mousedown = e => {
|
||||
if (
|
||||
(e.target.parentNode && e.target.parentNode.id == 'custom-menu') ||
|
||||
(e.target.parentNode &&
|
||||
e.target.parentNode.parentNode &&
|
||||
e.target.parentNode.parentNode.id == 'custom-menu')
|
||||
) {
|
||||
return
|
||||
}
|
||||
let menuElm = document.getElementById('custom-menu')
|
||||
if (menuElm) {
|
||||
_element.removeChild(menuElm)
|
||||
}
|
||||
}
|
||||
document.addEventListener('mousedown', eventListener[sdk.div_id].mousedown)
|
||||
eventListener[sdk.div_id].click = e => {
|
||||
if (
|
||||
(e.target.parentNode && e.target.parentNode.id == 'custom-menu') ||
|
||||
(e.target.parentNode &&
|
||||
e.target.parentNode.parentNode &&
|
||||
e.target.parentNode.parentNode.id == 'custom-menu')
|
||||
) {
|
||||
return
|
||||
}
|
||||
let menuElm = document.getElementById('custom-menu')
|
||||
if (menuElm) {
|
||||
_element.removeChild(menuElm)
|
||||
}
|
||||
}
|
||||
document.addEventListener('click', eventListener[sdk.div_id].click)
|
||||
|
||||
eventListener[sdk.div_id].mouseRightMenuEvent = new MouseEvent(sdk)
|
||||
eventListener[sdk.div_id].mouseRightMenuEvent.mouse_right(
|
||||
(movement, cartesian) => {
|
||||
if (YJ.Measure.GetMeasureStatus() || sdk.viewer.trackedEntity) {
|
||||
return
|
||||
}
|
||||
let entity = sdk.viewer.entities.getById('svg-control-points_0')
|
||||
if (entity && entity.show) {
|
||||
return
|
||||
}
|
||||
let menuElm = document.getElementById('custom-menu')
|
||||
if (menuElm) {
|
||||
_element.removeChild(menuElm)
|
||||
}
|
||||
let entityId = getEntityId(movement)
|
||||
let targetId
|
||||
if(Object.prototype.toString.call(entityId) === '[object Object]') {
|
||||
targetId = entityId.id
|
||||
entityId = entityId.parentId
|
||||
}
|
||||
let addedMenu = ''
|
||||
let that = sdk.entityMap.get(entityId)
|
||||
if (!that && entityId) {
|
||||
let array = entityId.split('-')
|
||||
array.splice(array.length - 1, 1)
|
||||
entityId = array.join('-')
|
||||
that = sdk.entityMap.get(entityId)
|
||||
}
|
||||
|
||||
if (that && that.picking) {
|
||||
addedMenu = `
|
||||
<span class="divider" style="display: block;border-top: 1px solid #ddd;margin: 5px;"></span>
|
||||
<ul class="added" style="list-style: none;padding: 0;margin: 0;font-size: 12px;">
|
||||
<li style="padding: 3px 10px;cursor: pointer;">属性</li>
|
||||
</ul>
|
||||
`
|
||||
}
|
||||
let position = tools.cartesian3Towgs84(cartesian, sdk.viewer)
|
||||
menuElm = document.createElement('div')
|
||||
menuElm.id = 'custom-menu'
|
||||
menuElm.style.position = 'absolute'
|
||||
menuElm.style.width = '110px'
|
||||
menuElm.style.backgroundColor = '#00000085'
|
||||
menuElm.style.color = '#ffffff'
|
||||
menuElm.style.padding = '6px 0'
|
||||
menuElm.style.boxShadow = '4px 4px 4px 0px rgba(0, 0, 0, 0.8)'
|
||||
menuElm.innerHTML = `
|
||||
<ul class="base" style="list-style: none;padding: 0;margin: 0;font-size: 12px;">
|
||||
<li style="padding: 3px 10px;cursor: pointer;">绕鼠标点旋转</li>
|
||||
</ul>
|
||||
${addedMenu}
|
||||
`
|
||||
_element.appendChild(menuElm)
|
||||
let left = movement.position.x
|
||||
let top = movement.position.y
|
||||
if (
|
||||
movement.position.x + menuElm.offsetWidth >
|
||||
_element.offsetWidth
|
||||
) {
|
||||
left = movement.position.x - menuElm.offsetWidth
|
||||
}
|
||||
if (
|
||||
movement.position.y + menuElm.offsetHeight >
|
||||
_element.offsetHeight
|
||||
) {
|
||||
top = movement.position.y - menuElm.offsetHeight
|
||||
}
|
||||
menuElm.style.left = left + 'px'
|
||||
menuElm.style.top = top + 'px'
|
||||
|
||||
menuElm.addEventListener('contextmenu', function(event) {
|
||||
event.preventDefault()
|
||||
})
|
||||
let liElms = menuElm.getElementsByTagName('li')
|
||||
let object = {}
|
||||
for (let i = 0; i < liElms.length; i++) {
|
||||
liElms[i].addEventListener('mouseover', () => {
|
||||
liElms[i].style.backgroundColor = '#5e5e5e'
|
||||
})
|
||||
liElms[i].addEventListener('mouseout', () => {
|
||||
liElms[i].style.backgroundColor = 'unset'
|
||||
})
|
||||
liElms[i].addEventListener('click', () => {
|
||||
let key = ''
|
||||
switch (liElms[i].innerHTML) {
|
||||
case '绕鼠标点旋转':
|
||||
object.position = position
|
||||
key = 'rotateAround'
|
||||
// this.rotateAround(position)
|
||||
break
|
||||
case '属性':
|
||||
if(targetId) {
|
||||
object.id = targetId
|
||||
object.parentId = that.options.id
|
||||
}
|
||||
else {
|
||||
object.id = that.options.id
|
||||
}
|
||||
key = 'attribute'
|
||||
// that.edit(true)
|
||||
// this.attribute(entityId)
|
||||
break
|
||||
}
|
||||
eventListener[sdk.div_id].callBack(key, object)
|
||||
_element.removeChild(menuElm)
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
function getEntityId(movement) {
|
||||
let pick = sdk.viewer.scene.pick(movement.position)
|
||||
if (pick) {
|
||||
if (pick.id) {
|
||||
if (pick.id.type && pick.id.type === 'vector' && pick.id.parentId) {
|
||||
return {
|
||||
parentId: pick.id.parentId,
|
||||
id: pick.id.id
|
||||
}
|
||||
}
|
||||
else if (pick.id.id) {
|
||||
return pick.id.id
|
||||
} else if (typeof pick.id == 'string') {
|
||||
return pick.id
|
||||
}
|
||||
} else {
|
||||
if (pick.primitive && pick.primitive.id) {
|
||||
return pick.primitive.id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getMouseRightMenuStatus(sdk) {
|
||||
if (!sdk || !sdk.div_id || !eventListener[sdk.div_id]) {
|
||||
return
|
||||
}
|
||||
else {
|
||||
return eventListener[sdk.div_id].status
|
||||
}
|
||||
}
|
||||
|
||||
export { MouseRightMenu, getMouseRightMenuStatus }
|
||||
156
src/Global/mouseRightMenu/index2.js
Normal file
156
src/Global/mouseRightMenu/index2.js
Normal file
@ -0,0 +1,156 @@
|
||||
/* 右键点击菜单 */
|
||||
import MouseEvent from '../../Event/index'
|
||||
import Tools from '../../Tools';
|
||||
import { rotateAround } from '../../Global/global'
|
||||
|
||||
|
||||
class mouseRightMenu {
|
||||
constructor(sdk, cd) {
|
||||
this.sdk = sdk
|
||||
this.callBack = cd
|
||||
this.mouseRightMenuEvent
|
||||
this.tools = new Tools()
|
||||
document.addEventListener('mousedown', (e)=>{
|
||||
if((e.target.parentNode && e.target.parentNode.id == "custom-menu") || (e.target.parentNode && e.target.parentNode.parentNode && e.target.parentNode.parentNode.id == "custom-menu")) {
|
||||
return
|
||||
}
|
||||
let menuElm = document.getElementById('custom-menu')
|
||||
if (menuElm) {
|
||||
this.sdk.viewer._element.removeChild(menuElm)
|
||||
}
|
||||
})
|
||||
document.addEventListener('click', (e)=>{
|
||||
if((e.target.parentNode && e.target.parentNode.id == "custom-menu") || (e.target.parentNode && e.target.parentNode.parentNode && e.target.parentNode.parentNode.id == "custom-menu")) {
|
||||
return
|
||||
}
|
||||
let menuElm = document.getElementById('custom-menu')
|
||||
if (menuElm) {
|
||||
this.sdk.viewer._element.removeChild(menuElm)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
open() {
|
||||
this.mouseRightMenuEvent && this.mouseRightMenuEvent.destroy()
|
||||
this.mouseRightMenuEvent = new MouseEvent(this.sdk)
|
||||
this.mouseRightMenuEvent.mouse_right((movement, cartesian) => {
|
||||
if (YJ.Measure.GetMeasureStatus()) {
|
||||
return
|
||||
}
|
||||
let menuElm = document.getElementById('custom-menu')
|
||||
if (menuElm) {
|
||||
this.sdk.viewer._element.removeChild(menuElm)
|
||||
}
|
||||
let entityId = this.getEntityId(movement)
|
||||
let addedMenu = ''
|
||||
let that = this.sdk.entityMap.get(entityId)
|
||||
if(!that && entityId) {
|
||||
let array = entityId.split("-");
|
||||
array.splice(array.length - 1, 1)
|
||||
entityId = array.join('-')
|
||||
that = this.sdk.entityMap.get(entityId)
|
||||
}
|
||||
if (that && that.picking) {
|
||||
addedMenu = `
|
||||
<span class="divider" style="display: block;border-top: 1px solid #ddd;margin: 5px;"></span>
|
||||
<ul class="added" style="list-style: none;padding: 0;margin: 0;font-size: 12px;">
|
||||
<li style="padding: 3px 10px;cursor: pointer;">属性</li>
|
||||
</ul>
|
||||
`
|
||||
}
|
||||
let position = this.tools.cartesian3Towgs84(cartesian, this.sdk.viewer)
|
||||
menuElm = document.createElement('div');
|
||||
menuElm.id = 'custom-menu'
|
||||
menuElm.style.position = 'absolute'
|
||||
menuElm.style.width = '110px'
|
||||
menuElm.style.backgroundColor = '#00000085'
|
||||
menuElm.style.color = '#ffffff'
|
||||
menuElm.style.padding = '6px 0'
|
||||
menuElm.style.boxShadow = '4px 4px 4px 0px rgba(0, 0, 0, 0.8)'
|
||||
menuElm.innerHTML = `
|
||||
<ul class="base" style="list-style: none;padding: 0;margin: 0;font-size: 12px;">
|
||||
<li style="padding: 3px 10px;cursor: pointer;">绕鼠标点旋转</li>
|
||||
</ul>
|
||||
${addedMenu}
|
||||
`
|
||||
this.sdk.viewer._element.appendChild(menuElm)
|
||||
let left = movement.position.x
|
||||
let top = movement.position.y
|
||||
if ((movement.position.x + menuElm.offsetWidth) > this.sdk.viewer._element.offsetWidth) {
|
||||
left = movement.position.x - menuElm.offsetWidth
|
||||
}
|
||||
if ((movement.position.y + menuElm.offsetHeight) > this.sdk.viewer._element.offsetHeight) {
|
||||
top = movement.position.y - menuElm.offsetHeight
|
||||
}
|
||||
menuElm.style.left = left + 'px'
|
||||
menuElm.style.top = top + 'px'
|
||||
|
||||
menuElm.addEventListener('contextmenu', function (event) {
|
||||
event.preventDefault();
|
||||
})
|
||||
let liElms = menuElm.getElementsByTagName('li')
|
||||
let object = {}
|
||||
for (let i = 0; i < liElms.length; i++) {
|
||||
liElms[i].addEventListener('mouseover', () => {
|
||||
liElms[i].style.backgroundColor = '#5e5e5e'
|
||||
})
|
||||
liElms[i].addEventListener('mouseout', () => {
|
||||
liElms[i].style.backgroundColor = 'unset'
|
||||
})
|
||||
liElms[i].addEventListener('click', () => {
|
||||
switch (liElms[i].innerHTML) {
|
||||
case '绕中心点旋转':
|
||||
object.position = position
|
||||
// this.rotateAround(position)
|
||||
break
|
||||
case '属性':
|
||||
object.id = that.options.id
|
||||
// that.edit(true)
|
||||
// this.attribute(entityId)
|
||||
break
|
||||
}
|
||||
|
||||
this.callBack(liElms[i].innerHTML, object)
|
||||
this.sdk.viewer._element.removeChild(menuElm)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
getEntityId(movement) {
|
||||
let pick = this.sdk.viewer.scene.pick(movement.position)
|
||||
if (pick) {
|
||||
if (pick.id) {
|
||||
if (pick.id.id) {
|
||||
return pick.id.id
|
||||
}
|
||||
else if (typeof pick.id == 'string') {
|
||||
return pick.id
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (pick.primitive && pick.primitive.id) {
|
||||
return pick.primitive.id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rotateAround(position) {
|
||||
rotateAround(this.sdk, position)
|
||||
}
|
||||
|
||||
attribute(entityId) {
|
||||
if(entityId.endsWith('-label')) {
|
||||
entityId = entityId.replace('-label', '')
|
||||
}
|
||||
let that = this.sdk.entityMap.get(entityId)
|
||||
that && that.edit(true)
|
||||
}
|
||||
|
||||
close() {
|
||||
this.mouseRightMenuEvent && this.mouseRightMenuEvent.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
export default mouseRightMenu
|
||||
397
src/In/index.js
Normal file
397
src/In/index.js
Normal file
@ -0,0 +1,397 @@
|
||||
import { on } from '../on'
|
||||
import YJEarth from '../YJEarth'
|
||||
import {
|
||||
getCurrentView,
|
||||
setDefaultView,
|
||||
flyTo,
|
||||
CameraController,
|
||||
CesiumContainer,
|
||||
setBillboardDefaultUrl,
|
||||
getBillboardDefaultUrl,
|
||||
setGroundCover,
|
||||
getGroundCover,
|
||||
setBimPickStatus,
|
||||
getBimPickStatus,
|
||||
FlwStatusSwitch,
|
||||
JwwStatusSwitch,
|
||||
rotateAround,
|
||||
getCoordinateSystem,
|
||||
setCoordinateSystem,
|
||||
cameraChanged,
|
||||
setMaximumRequestsPerServer,
|
||||
setKeyboardEventActive,
|
||||
getTheme,
|
||||
setTheme,
|
||||
getCesiumManageIndexexDBState,
|
||||
setCesiumManageIndexexDBState,
|
||||
getCesiumIndexedDBMaxSize,
|
||||
setCesiumIndexedDBMaxSize,
|
||||
getCesiumIndexedDBCurrentSize,
|
||||
enablePerspective,
|
||||
closeRotateAround
|
||||
} from '../Global/global'
|
||||
import { SheetIndexStatusSwitch, changeScale as SheetIndexShangeScale } from '../Global/SheetIndex'
|
||||
import { switchCluster } from '../Global/cluster/cluster'
|
||||
import DTH from '../Global/DTH'
|
||||
import {
|
||||
closeLeftClick,
|
||||
openLeftClick,
|
||||
closeRightClick,
|
||||
openRightClick,
|
||||
openMove,
|
||||
closeMove
|
||||
} from '../Global/ClickCallback'
|
||||
import { startScreenRecord, stopScreenRecord } from '../Global/ScreenRecord'
|
||||
import { ScreenShot, ScreenShotHD } from '../Global/ScreenShot'
|
||||
import ExportKml from '../Global/ExportKml'
|
||||
import { setSkin } from '../Global/Skin'
|
||||
import {
|
||||
open as FlyRoamOpen,
|
||||
close as FlyRoamClose,
|
||||
flyTo as FlyRoamFlyTo,
|
||||
setRepeat as FlyRoamSetRepeat,
|
||||
cease as FlyRoamCease
|
||||
} from '../Global/FlyRoam'
|
||||
import {
|
||||
rain,
|
||||
snow,
|
||||
fog,
|
||||
nightVision,
|
||||
skyStarry,
|
||||
illumination
|
||||
} from '../Global/efflect'
|
||||
import { open as mapxOpen, close as mapxClose } from '../Global/MapX'
|
||||
import {
|
||||
on as multiViewportModeOn,
|
||||
off as multiViewportModeOff,
|
||||
get2DView
|
||||
} from '../Global/MultiViewportMode'
|
||||
import { MouseCoordinate } from '../Global/MouseCoordinate'
|
||||
import { MouseRightMenu } from '../Global/mouseRightMenu'
|
||||
import { dialog as ContourDialog } from '../Global/Contour'
|
||||
import { on as SplitScreenOn, off as SplitScreenOff, setActiveId as SplitScreenSetActiveId } from '../Global/SplitScreen'
|
||||
import LocateCurrent from '../Obj/Base/LocateCurrent'
|
||||
|
||||
import { Clear as AnalysisClear } from '../Obj/Analysis/clear'
|
||||
import CutFillAnalysis from '../Obj/Analysis/CutFill'
|
||||
import Submerge from '../Obj/Analysis/Submerge'
|
||||
import ViewShed from '../Obj/Analysis/ViewShed'
|
||||
import CircleViewShed from '../Obj/Analysis/CircleViewShed'
|
||||
// import Test2 from '../Obj/Analysis/test2'
|
||||
import SlopeAspect from '../Obj/Analysis/SlopeAspect'
|
||||
import Profile from '../Obj/Analysis/Profile'
|
||||
import Visibility from '../Obj/Analysis/Visibility'
|
||||
import Contour from '../Obj/Analysis/Contour'
|
||||
import Section from '../Obj/Analysis/Section'
|
||||
import TerrainExcavation from '../Obj/Analysis/TerrainExcavation'
|
||||
import Flat from '../Obj/Analysis/Flat'
|
||||
|
||||
import MeasureDistance from '../Measure/MeasureDistance'
|
||||
import MeasureProjectionDistance from '../Measure/MeasureProjectionDistance'
|
||||
import MeasureSlopeDistance from '../Measure/MeasureSlopeDistance'
|
||||
import { Clear } from '../Measure/clear'
|
||||
import MeasureTyArea from '../Measure/MeasureTyArea'
|
||||
import MeasureTdArea from '../Measure/MeasureTdArea'
|
||||
import MeasureTriangle from '../Measure/MeasureTriangle'
|
||||
import MeasureLocation from '../Measure/MeasureLocation'
|
||||
import MeasureHeight from '../Measure/MeasureHeight'
|
||||
import MeasureAngle from '../Measure/MeasureAngle'
|
||||
import MeasureAzimuth from '../Measure/MeasureAzimuth'
|
||||
import DrawPolyline from '../Draw/drawPolyline'
|
||||
import DrawPolygon from '../Draw/drawPolygon'
|
||||
import DrawPoint from '../Draw/drawPoint'
|
||||
import DrawCircle from '../Draw/drawCircle'
|
||||
import DrawElliptic from '../Draw/drawElliptic'
|
||||
import DrawAttackArrow from '../Draw/drawAttackArrow'
|
||||
import DrawPincerArrow from '../Draw/drawPincerArrow'
|
||||
import DrawStraightArrow from '../Draw/drawStraightArrow'
|
||||
import DrawRect from '../Draw/drawRect'
|
||||
import DrawAssemble from '../Draw/drawAssemble'
|
||||
import DrawSector from '../Draw/drawSector'
|
||||
import {
|
||||
ArcgisBLUEImagery,
|
||||
ArcgisLWImagery,
|
||||
ArcgisWXImagery
|
||||
} from '../Obj/Base/BaseSource/BaseLayer/ArcgisImagery'
|
||||
import {
|
||||
GDLWImagery,
|
||||
GDSLImagery,
|
||||
GDWXImagery
|
||||
} from '../Obj/Base/BaseSource/BaseLayer/GdImagery'
|
||||
import Tileset from '../Obj/Base/BaseSource/BaseTileset/Tileset'
|
||||
import BIM from '../Obj/Base/BaseSource/BaseTileset/BIM'
|
||||
import Model from '../Obj/Base/BaseSource/BaseModel/Model'
|
||||
import Model2 from '../Obj/Base/BaseSource/BaseModel/Model2'
|
||||
import Layer from '../Obj/Base/BaseSource/BaseLayer/Layer'
|
||||
import Layer3rdparty from '../Obj/Base/BaseSource/BaseLayer/Layer3rdparty'
|
||||
import Terrain from '../Obj/Base/BaseSource/BaseTerrain'
|
||||
import Flame from '../Obj/Base/ParticleEffects/Flame'
|
||||
import Smoke from '../Obj/Base/ParticleEffects/Smoke'
|
||||
import Fountain from '../Obj/Base/ParticleEffects/Fountain'
|
||||
import Spout from '../Obj/Base/ParticleEffects/Spout'
|
||||
import PolygonObject from '../Obj/Base/PolygonObject'
|
||||
import PolyhedronObject from '../Obj/Base/PolyhedronObject'
|
||||
// import PolyhedronObject2 from '../Obj/Base/PolyhedronObject2'
|
||||
import AssembleObject from '../Obj/Base/AssembleObject'
|
||||
import AttackArrowObject from '../Obj/Base/AttackArrowObject'
|
||||
import PincerArrowObject from '../Obj/Base/PincerArrowObject'
|
||||
import StraightArrowObject from '../Obj/Base/StraightArrowObject'
|
||||
import CircleDiffuse from '../Obj/Base/CircleDiffuse'
|
||||
import CircleObject from '../Obj/Base/CircleObject'
|
||||
import EllipseObject from '../Obj/Base/EllipseObject'
|
||||
import WallStereoscopic from '../Obj/Base/WallStereoscopic'
|
||||
import WallRealStereoscopic from '../Obj/Base/WallRealStereoscopic'
|
||||
// import Corridor from '../Obj/Base/Corridor'
|
||||
import BillboardObject from '../Obj/Base/BillboardObject'
|
||||
import PolylineObject from '../Obj/Base/PolylineObject'
|
||||
import CurvelineObject from '../Obj/Base/CurvelineObject'
|
||||
// import EllipseObject from '../Obj/Base/EllipseObject'
|
||||
import Explosion from '../Obj/Base/Explosion'
|
||||
import RadarScan from '../Obj/Base/RadarScan'
|
||||
import RadarScanStereoscopic from '../Obj/Base/RadarScanStereoscopic'
|
||||
import SectorObject from '../Obj/Base/SectorObject'
|
||||
import KML from '../Obj/Base/KML'
|
||||
import GeoJson from '../Obj/Base/GeoJson'
|
||||
import WaterSurface from '../Obj/Base/WaterSurface'
|
||||
// import ItineraryMove from '../Obj/Base/ItineraryMove'
|
||||
import TrajectoryMotion from '../Obj/Base/TrajectoryMotion'
|
||||
import TrajectoryMotionObject from '../Obj/Base/TrajectoryMotionObject'
|
||||
import Road from '../Obj/Base/Road'
|
||||
import Graffiti from '../Obj/Base/Graffiti'
|
||||
import GroundImage from '../Obj/Base/GroundImage'
|
||||
import GroundSvg from '../Obj/Base/GroundSvg'
|
||||
import RoutePlanning from '../Obj/Base/RoutePlanning'
|
||||
import Shp from '../Obj/Base/Shp'
|
||||
import Vector from '../Obj/Base/Vector'
|
||||
// import Text3D from "../Obj/Base/TextObject/3DText";
|
||||
import GroundText from '../Obj/Base/TextObject/GroundText'
|
||||
import StandText from '../Obj/Base/TextObject/StandText'
|
||||
import { Clear as ClearAllRoutePlanning } from '../Obj/Base/RoutePlanning/clear'
|
||||
import RichText from '../Obj/Element/richText'
|
||||
import Tools from '../Tools'
|
||||
import { Proj } from '../Tools/proj'
|
||||
import CoordTransform from '../transform/CoordTransform'
|
||||
import LoadObjModel from '../Obj/Base/LoadObjModel'
|
||||
import DZXJLoadObjModel from '../DZ/XJ/LoadObjModel'
|
||||
import BatchLoadObjModel from '../DZ/XJ/BatchLoadObjModel'
|
||||
import Heatmap from '../Obj/Base/Heatmap'
|
||||
import FlyRoam from '../Obj/Base/FlyRoam'
|
||||
import Dialog from '../Obj/Element/Dialog'
|
||||
// import AirLine from '../Obj/AirLine'
|
||||
// import GenerateRoute from '../Obj/AirLine/GenerateRoute'
|
||||
import newAirLine from '../Obj/AirLine/pointRoute.js'
|
||||
import Frustum from '../Obj/AirLine/frustum'
|
||||
import DrawTakeOff from '../Obj/AirLine/DrawTakeOff'
|
||||
|
||||
const YJEarthismeasuring = Symbol('测量状态')
|
||||
const screenRecord = Symbol('录屏对象')
|
||||
if (!window.YJ) {
|
||||
window.YJ = {
|
||||
on,
|
||||
Obj: {
|
||||
ArcgisWXImagery,
|
||||
ArcgisBLUEImagery,
|
||||
ArcgisLWImagery,
|
||||
GDLWImagery,
|
||||
GDWXImagery,
|
||||
GDSLImagery,
|
||||
Tileset,
|
||||
BIM,
|
||||
Layer,
|
||||
Layer3rdparty,
|
||||
Terrain,
|
||||
Flame,
|
||||
Smoke,
|
||||
Fountain,
|
||||
Spout,
|
||||
WaterSurface,
|
||||
CircleDiffuse,
|
||||
CircleObject,
|
||||
EllipseObject,
|
||||
RadarScan,
|
||||
RadarScanStereoscopic,
|
||||
SectorObject,
|
||||
WallStereoscopic,
|
||||
WallRealStereoscopic,
|
||||
KML,
|
||||
GeoJson,
|
||||
// ItineraryMove,
|
||||
BillboardObject,
|
||||
PolygonObject,
|
||||
PolyhedronObject,
|
||||
// PolyhedronObject2,
|
||||
AssembleObject,
|
||||
AttackArrowObject,
|
||||
PincerArrowObject,
|
||||
StraightArrowObject,
|
||||
// Corridor,
|
||||
PolylineObject,
|
||||
CurvelineObject,
|
||||
// EllipseObject,
|
||||
Explosion,
|
||||
Model,
|
||||
Model2,
|
||||
TrajectoryMotion,
|
||||
TrajectoryMotionObject,
|
||||
Road,
|
||||
Graffiti,
|
||||
GroundImage,
|
||||
GroundSvg,
|
||||
RoutePlanning,
|
||||
Shp,
|
||||
Vector,
|
||||
// Text3D,
|
||||
GroundText,
|
||||
StandText,
|
||||
RichText,
|
||||
LocateCurrent,
|
||||
LoadObjModel,
|
||||
Heatmap,
|
||||
FlyRoam,
|
||||
// AirLine,
|
||||
newAirLine,
|
||||
FRUSTUN: Frustum,
|
||||
// GenerateRoute
|
||||
Dialog
|
||||
},
|
||||
YJEarth,
|
||||
Tools,
|
||||
Proj,
|
||||
Global: {
|
||||
getCurrentView,
|
||||
setDefaultView,
|
||||
switchCluster,
|
||||
openLeftClick,
|
||||
closeLeftClick,
|
||||
closeRightClick,
|
||||
openRightClick,
|
||||
openMove,
|
||||
closeMove,
|
||||
ScreenRecord: {
|
||||
start: () => {
|
||||
return startScreenRecord(screenRecord)
|
||||
},
|
||||
stop: () => {
|
||||
return stopScreenRecord()
|
||||
},
|
||||
screenRecord: null
|
||||
},
|
||||
MapX: {
|
||||
open: mapxOpen,
|
||||
close: mapxClose
|
||||
},
|
||||
ScreenShot,
|
||||
ScreenShotHD,
|
||||
ExportKml,
|
||||
FlyRoam: {
|
||||
open: FlyRoamOpen,
|
||||
close: FlyRoamClose,
|
||||
flyTo: FlyRoamFlyTo,
|
||||
setRepeat: FlyRoamSetRepeat,
|
||||
cease: FlyRoamCease
|
||||
},
|
||||
flyTo,
|
||||
efflect: { rain, snow, fog, nightVision, skyStarry, illumination },
|
||||
CameraController,
|
||||
CesiumContainer,
|
||||
setBillboardDefaultUrl,
|
||||
getBillboardDefaultUrl,
|
||||
multiViewportMode: {
|
||||
on: multiViewportModeOn,
|
||||
off: multiViewportModeOff,
|
||||
get2DView
|
||||
},
|
||||
MouseCoordinate,
|
||||
MouseRightMenu,
|
||||
setGroundCover,
|
||||
getGroundCover,
|
||||
setBimPickStatus,
|
||||
getBimPickStatus,
|
||||
FlwStatusSwitch,
|
||||
JwwStatusSwitch,
|
||||
rotateAround,
|
||||
getCoordinateSystem,
|
||||
setCoordinateSystem,
|
||||
DTH,
|
||||
cameraChanged,
|
||||
setMaximumRequestsPerServer,
|
||||
setKeyboardEventActive,
|
||||
setSkin,
|
||||
getTheme,
|
||||
setTheme,
|
||||
getCesiumManageIndexexDBState,
|
||||
setCesiumManageIndexexDBState,
|
||||
getCesiumIndexedDBMaxSize,
|
||||
setCesiumIndexedDBMaxSize,
|
||||
getCesiumIndexedDBCurrentSize,
|
||||
enablePerspective,
|
||||
closeRotateAround,
|
||||
SheetIndexStatusSwitch,
|
||||
SheetIndexShangeScale,
|
||||
splitScreen: {
|
||||
on: SplitScreenOn,
|
||||
off: SplitScreenOff,
|
||||
setActiveId: SplitScreenSetActiveId
|
||||
},
|
||||
Contour: ContourDialog
|
||||
}, //测量
|
||||
Measure: {
|
||||
GetMeasureStatus: () => {
|
||||
return YJ.Measure[YJEarthismeasuring]
|
||||
},
|
||||
SetMeasureStatus: (status = false) => {
|
||||
YJ.Measure[YJEarthismeasuring] = status
|
||||
},
|
||||
Clear,
|
||||
Measures: [],
|
||||
MeasureDistance,
|
||||
MeasureProjectionDistance,
|
||||
MeasureSlopeDistance,
|
||||
MeasureTyArea,
|
||||
MeasureTdArea,
|
||||
MeasureTriangle,
|
||||
MeasureLocation,
|
||||
MeasureHeight,
|
||||
MeasureAngle,
|
||||
MeasureAzimuth
|
||||
},
|
||||
Draw: {
|
||||
DrawPolyline,
|
||||
DrawPolygon,
|
||||
DrawPoint,
|
||||
DrawCircle,
|
||||
DrawElliptic,
|
||||
DrawAttackArrow,
|
||||
DrawPincerArrow,
|
||||
DrawStraightArrow,
|
||||
DrawRect,
|
||||
DrawAssemble,
|
||||
DrawSector,
|
||||
DrawTakeOff,
|
||||
},
|
||||
// 分析
|
||||
Analysis: {
|
||||
Clear: AnalysisClear,
|
||||
CutFillAnalysis,
|
||||
Submerge,
|
||||
ViewShed,
|
||||
CircleViewShed,
|
||||
// Test2,
|
||||
SlopeAspect,
|
||||
Profile,
|
||||
Visibility,
|
||||
Contour,
|
||||
Section,
|
||||
TerrainExcavation,
|
||||
Flat,
|
||||
Analyses: []
|
||||
},
|
||||
CoordTransform,
|
||||
RoutePlanningArrays: [],
|
||||
ClearAllRoutePlanning
|
||||
}
|
||||
if (process.env.DZ === 'xj') {
|
||||
window.YJ.Obj.LoadObjModel = DZXJLoadObjModel
|
||||
window.YJ.Obj.BatchLoadObjModel = BatchLoadObjModel
|
||||
}
|
||||
}
|
||||
209
src/Measure/MeasureAngle/index.js
Normal file
209
src/Measure/MeasureAngle/index.js
Normal file
@ -0,0 +1,209 @@
|
||||
/**
|
||||
* @name: index
|
||||
* @author: Administrator
|
||||
* @date: 2023-12-29 10:11
|
||||
* @description:index
|
||||
* @update: 2023-12-29 10:11
|
||||
*/
|
||||
import Measure from "../index";
|
||||
|
||||
class MeasureAngle extends Measure {
|
||||
constructor(sdk) {
|
||||
super(sdk, { text: "左键开始,右键取消" });
|
||||
this.cachePositions = []
|
||||
this.positions = []
|
||||
this.arcPositions = []
|
||||
this.line_id = ""
|
||||
this.label_id = ""
|
||||
this.arc_id = ""
|
||||
this.bearing = 0
|
||||
}
|
||||
|
||||
createPolyline() {
|
||||
let that = this
|
||||
let id = that.randomString()
|
||||
that.viewer.entities.add(new Cesium.Entity({
|
||||
id,
|
||||
polyline: {
|
||||
positions: new Cesium.CallbackProperty(() => {
|
||||
return that.positions
|
||||
}, false),
|
||||
clampToGround: true,
|
||||
width: 5,
|
||||
material: new Cesium.Color.fromCssColorString(that.options.color || that.defaultColor),
|
||||
zIndex: 99999999
|
||||
}
|
||||
}))
|
||||
return id
|
||||
}
|
||||
|
||||
end() {
|
||||
super.end();
|
||||
}
|
||||
|
||||
destroy() {
|
||||
super.destroy();
|
||||
let arr = [this.line_id, this.label_id, this.arc_id]
|
||||
arr.forEach(id => {
|
||||
if (id)
|
||||
this.remove_entity(id)
|
||||
})
|
||||
}
|
||||
|
||||
cancel() {
|
||||
this.end()
|
||||
this.destroy()
|
||||
}
|
||||
|
||||
caculateAngle(points = []) {
|
||||
let p1 = this.cartesian3Towgs84(points[0], this.viewer)
|
||||
let p2 = this.cartesian3Towgs84(points[1], this.viewer)
|
||||
let p3 = this.cartesian3Towgs84(points[2], this.viewer)
|
||||
let point1 = turf.point([p1.lng, p1.lat]);
|
||||
let point2 = turf.point([p2.lng, p2.lat]);
|
||||
let point3 = turf.point([p3.lng, p3.lat]);
|
||||
let options = { units: 'kilometers' };
|
||||
let distance1 = turf.rhumbDistance(point1, point2, options);
|
||||
let distance2 = turf.rhumbDistance(point3, point2, options);
|
||||
let distance = distance1
|
||||
if (distance1 > distance2) {
|
||||
distance = distance2
|
||||
}
|
||||
|
||||
let bearing1 = turf.rhumbBearing(point1, point2)
|
||||
let bearing2 = turf.rhumbBearing(point3, point2)
|
||||
|
||||
let bearing = Math.abs(((bearing1 - bearing2) + 360) % 360)
|
||||
if (bearing > 180) {
|
||||
this.bearing = 360 - bearing
|
||||
} else {
|
||||
this.bearing = bearing
|
||||
}
|
||||
this.bearing = this.bearing.toFixed(2)
|
||||
|
||||
let b1 = (bearing1 - 180)
|
||||
let b2 = (bearing2 - 180)
|
||||
let arc = turf.lineArc(point2, (distance / 3), b2, b1);
|
||||
if (bearing > 180) {
|
||||
arc = turf.lineArc(point2, (distance / 3), b1, b2);
|
||||
}
|
||||
let arcPos = []
|
||||
for (let i = 0; i < arc.geometry.coordinates.length; i++) {
|
||||
arcPos.push(Cesium.Cartesian3.fromDegrees(arc.geometry.coordinates[i][0], arc.geometry.coordinates[i][1]))
|
||||
}
|
||||
this.arcPositions = arcPos
|
||||
|
||||
// if (bearing1 > 0 && bearing2 > 0) {
|
||||
// this.bearing = Math.abs(bearing1 - bearing2).toFixed(1)
|
||||
// } else if (bearing1 < 0 && bearing2 < 0) {
|
||||
// this.bearing = Math.abs(bearing1 - bearing2).toFixed(1)
|
||||
// } else if (bearing1 > 0 && bearing2 < 0) {
|
||||
// this.bearing = Math.abs(360 - Math.abs(bearing2) - bearing1).toFixed(1)
|
||||
// } else {
|
||||
// this.bearing = Math.abs(360 - Math.abs(bearing1) - bearing2).toFixed(1)
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
start() {
|
||||
if (!YJ.Measure.GetMeasureStatus()) {
|
||||
super.start();
|
||||
|
||||
let leftEvent = (movement, car) => {
|
||||
if (this.ids.length === 0) {
|
||||
//需要创建一个线
|
||||
this.line_id = this.createPolyline()
|
||||
}
|
||||
|
||||
this.ids.push(this.create_point(car))
|
||||
this.tip.setPosition(car, movement.position.x, movement.position.y)
|
||||
this.cachePositions.push(car)
|
||||
if (this.cachePositions.length) {
|
||||
this.positions = this.cachePositions.concat(car)
|
||||
}
|
||||
if (this.ids.length === 2) {
|
||||
this.label_id = Cesium.createGuid()
|
||||
this.arc_id = Cesium.createGuid()
|
||||
let p = this.cartesian3Towgs84(car, this.viewer)
|
||||
this.sampleHeightMostDetailed([p]).then((res) => {
|
||||
let arc = this.viewer.entities.add({
|
||||
id: this.arc_id,
|
||||
polyline: {
|
||||
positions: new Cesium.CallbackProperty(() => {
|
||||
return this.arcPositions
|
||||
}, false),
|
||||
clampToGround: true,
|
||||
width: 5,
|
||||
material: new Cesium.Color.fromCssColorString(this.options.color || this.defaultColor),
|
||||
zIndex: 99999999
|
||||
}
|
||||
})
|
||||
let label = this.viewer.entities.add({
|
||||
id: this.label_id,
|
||||
position: Cesium.Cartesian3.fromDegrees(p.lng, p.lat, (res[0].height || 0) + 0.1),
|
||||
label: {
|
||||
text: new Cesium.CallbackProperty(() => {
|
||||
return "夹角:" + this.bearing + "°"
|
||||
}, false),
|
||||
font: '20px Microsoft YaHei',
|
||||
fillColor: Cesium.Color.fromCssColorString('#f1e605'),
|
||||
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
|
||||
//标注的遮挡距离设置为100则视角与标注的距离大于100米时会有遮挡
|
||||
// distanceDisplayCondition: this.distanceDisplayCondition,
|
||||
scale: 1,
|
||||
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
||||
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
if (this.ids.length === 3) {
|
||||
this.caculateAngle([this.positions[0], this.positions[1], this.positions[2]])
|
||||
//需要停止绘制
|
||||
this.end()
|
||||
}
|
||||
|
||||
}
|
||||
this.event.mouse_left(leftEvent)
|
||||
this.event.mouse_move((movement, car) => {
|
||||
this.tip.setPosition(car, movement.endPosition.x, movement.endPosition.y)
|
||||
if (this.cachePositions.length) {
|
||||
this.positions = this.cachePositions.concat(car)
|
||||
}
|
||||
if (this.positions.length > 2) {
|
||||
//需要开始计算夹角
|
||||
this.caculateAngle([this.positions[0], this.positions[1], this.positions[2]])
|
||||
}
|
||||
})
|
||||
this.event.mouse_right((movement, car) => {
|
||||
this.cancel()
|
||||
})
|
||||
|
||||
this.event.gesture_pinck_start((movement, cartesian) => {
|
||||
let startTime = new Date()
|
||||
let pos = {
|
||||
position: {
|
||||
x: (movement.position1.x + movement.position2.x) / 2,
|
||||
y: (movement.position1.y + movement.position2.y) / 2
|
||||
}
|
||||
}
|
||||
this.event.gesture_pinck_end(() => {
|
||||
let endTime = new Date()
|
||||
if (endTime - startTime >= 500) {
|
||||
// 长按取消
|
||||
this.cancel()
|
||||
}
|
||||
else {
|
||||
leftEvent(pos, cartesian)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export default MeasureAngle
|
||||
206
src/Measure/MeasureAzimuth/index.js
Normal file
206
src/Measure/MeasureAzimuth/index.js
Normal file
@ -0,0 +1,206 @@
|
||||
import Measure from "../index";
|
||||
|
||||
class MeasureAzimuth extends Measure {
|
||||
/**
|
||||
* @constructor
|
||||
* @param sdk
|
||||
* @description 方位角测量
|
||||
* */
|
||||
constructor(sdk) {
|
||||
super(sdk, { text: "左键开始,右键取消" });
|
||||
this.cachePositions = []
|
||||
this.positions = []
|
||||
this.arcPositions = []
|
||||
this.line_id = ""
|
||||
this.label_id = ""
|
||||
this.arc_id = ""
|
||||
this.bearing = 0
|
||||
}
|
||||
|
||||
createPolyline() {
|
||||
let that = this
|
||||
let id = that.randomString()
|
||||
that.viewer.entities.add(new Cesium.Entity({
|
||||
id,
|
||||
polyline: {
|
||||
positions: new Cesium.CallbackProperty(() => {
|
||||
return that.positions
|
||||
}, false),
|
||||
clampToGround: true,
|
||||
width: 5,
|
||||
material: new Cesium.Color.fromCssColorString(that.options.color || that.defaultColor),
|
||||
zIndex: 99999999
|
||||
}
|
||||
}))
|
||||
return id
|
||||
}
|
||||
|
||||
end() {
|
||||
super.end();
|
||||
}
|
||||
|
||||
destroy() {
|
||||
super.destroy();
|
||||
let arr = [this.line_id, this.label_id, this.arc_id]
|
||||
arr.forEach(id => {
|
||||
if (id)
|
||||
this.remove_entity(id)
|
||||
})
|
||||
}
|
||||
|
||||
cancel() {
|
||||
this.end()
|
||||
this.destroy()
|
||||
}
|
||||
|
||||
caculateAngle(line1 = [], line2 = []) {
|
||||
let c = this.cartesian3Towgs84(line2[1], this.viewer)
|
||||
let p2 = this.cartesian3Towgs84(line2[0], this.viewer)
|
||||
let center = turf.point([c.lng, c.lat])
|
||||
let point2 = turf.point([p2.lng, p2.lat])
|
||||
let bearing = this.rhumbBearing(p2, c)
|
||||
this.bearing = (180 + bearing).toFixed(2)
|
||||
|
||||
let distance = turf.rhumbDistance(center, point2, { units: 'kilometers' });
|
||||
let arc = turf.lineArc(center, (distance/3), 0, this.bearing);
|
||||
let arcPos = []
|
||||
for (let i = 0; i < arc.geometry.coordinates.length; i++) {
|
||||
arcPos.push(Cesium.Cartesian3.fromDegrees(arc.geometry.coordinates[i][0], arc.geometry.coordinates[i][1]))
|
||||
}
|
||||
this.arcPositions = arcPos
|
||||
}
|
||||
|
||||
|
||||
start() {
|
||||
if (!YJ.Measure.GetMeasureStatus()) {
|
||||
super.start();
|
||||
|
||||
let leftEvent = async (movement, car) => {
|
||||
if (this.ids.length === 0) {
|
||||
//需要创建一个线
|
||||
this.line_id = this.createPolyline()
|
||||
}
|
||||
this.tip.setPosition(car, movement.position.x, movement.position.y)
|
||||
if (this.cachePositions.length) {
|
||||
this.positions = this.cachePositions.concat(car)
|
||||
let p = this.cartesian3Towgs84(car, this.viewer)
|
||||
let pc = this.cartesian3Towgs84(this.positions[1], this.viewer)
|
||||
let from = turf.point([pc.lng, pc.lat]);
|
||||
let to = turf.point([p.lng, p.lat]);
|
||||
let options = { units: 'kilometers' };
|
||||
let distance = turf.rhumbDistance(from, to, options);
|
||||
|
||||
let bearing = 0;
|
||||
let destination = turf.destination(from, distance, bearing, options);
|
||||
this.positions[0] = Cesium.Cartesian3.fromDegrees(...destination.geometry.coordinates)
|
||||
}
|
||||
this.cachePositions.push(car)
|
||||
this.cachePositions.push(car)
|
||||
if (this.positions.length > 2) {
|
||||
//需要开始计算夹角
|
||||
this.caculateAngle(
|
||||
[this.positions[0], this.positions[1]],
|
||||
[this.positions[2], this.positions[1]])
|
||||
}
|
||||
if (this.ids.length >= 2) {
|
||||
//需要停止绘制
|
||||
this.end()
|
||||
return
|
||||
}
|
||||
|
||||
this.ids.push(this.create_point(car))
|
||||
this.ids.push(this.create_point(car))
|
||||
if (this.ids.length === 2) {
|
||||
this.label_id = Cesium.createGuid()
|
||||
this.arc_id = Cesium.createGuid()
|
||||
let p = this.cartesian3Towgs84(car, this.viewer)
|
||||
let res = await this.sampleHeightMostDetailed([p])
|
||||
|
||||
let arc = this.viewer.entities.add({
|
||||
id: this.arc_id,
|
||||
polyline: {
|
||||
positions: new Cesium.CallbackProperty(() => {
|
||||
return this.arcPositions
|
||||
}, false),
|
||||
clampToGround: true,
|
||||
width: 5,
|
||||
material: new Cesium.Color.fromCssColorString(this.options.color || this.defaultColor),
|
||||
zIndex: 99999999
|
||||
}
|
||||
})
|
||||
|
||||
let label = this.viewer.entities.add({
|
||||
id: this.label_id,
|
||||
position: Cesium.Cartesian3.fromDegrees(p.lng, p.lat, (res[0].height || 0) + 0.1),
|
||||
label: {
|
||||
text: new Cesium.CallbackProperty(() => {
|
||||
return "方位夹角:" + this.bearing + "°"
|
||||
}, false),
|
||||
font: '20px Microsoft YaHei',
|
||||
fillColor: Cesium.Color.fromCssColorString('#f1e605'),
|
||||
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
|
||||
//标注的遮挡距离设置为100则视角与标注的距离大于100米时会有遮挡
|
||||
// distanceDisplayCondition: this.distanceDisplayCondition,
|
||||
scale: 1,
|
||||
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
||||
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
||||
}
|
||||
})
|
||||
//需要创建夹角的显示效果
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
this.event.mouse_left(leftEvent)
|
||||
this.event.mouse_move((movement, car) => {
|
||||
this.tip.setPosition(car, movement.endPosition.x, movement.endPosition.y)
|
||||
if (this.cachePositions.length) {
|
||||
this.positions = this.cachePositions.concat(car)
|
||||
let p = this.cartesian3Towgs84(car, this.viewer)
|
||||
let pc = this.cartesian3Towgs84(this.positions[1], this.viewer)
|
||||
let from = turf.point([pc.lng, pc.lat]);
|
||||
let to = turf.point([p.lng, p.lat]);
|
||||
let options = { units: 'kilometers' };
|
||||
let distance = turf.rhumbDistance(from, to, options);
|
||||
|
||||
let bearing = 0;
|
||||
let destination = turf.destination(from, distance, bearing, options);
|
||||
this.positions[0] = Cesium.Cartesian3.fromDegrees(...destination.geometry.coordinates)
|
||||
}
|
||||
if (this.positions.length > 2) {
|
||||
//需要开始计算夹角
|
||||
this.caculateAngle(
|
||||
[this.positions[0], this.positions[1]],
|
||||
[this.positions[2], this.positions[1]])
|
||||
}
|
||||
})
|
||||
this.event.mouse_right((movement, car) => {
|
||||
this.cancel()
|
||||
})
|
||||
|
||||
this.event.gesture_pinck_start((movement, cartesian) => {
|
||||
let startTime = new Date()
|
||||
let pos = {
|
||||
position: {
|
||||
x: (movement.position1.x + movement.position2.x) / 2,
|
||||
y: (movement.position1.y + movement.position2.y) / 2
|
||||
}
|
||||
}
|
||||
this.event.gesture_pinck_end(() => {
|
||||
let endTime = new Date()
|
||||
if (endTime - startTime >= 500) {
|
||||
// 长按取消
|
||||
this.cancel()
|
||||
}
|
||||
else {
|
||||
leftEvent(pos, cartesian)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export default MeasureAzimuth
|
||||
18
src/Measure/MeasureCircle/index.js
Normal file
18
src/Measure/MeasureCircle/index.js
Normal file
@ -0,0 +1,18 @@
|
||||
import Measure from '../index'
|
||||
|
||||
/**@extends Measure*/
|
||||
class MeasureCircle extends Measure {
|
||||
constructor(sdk, options = {}) {
|
||||
super(sdk, options)
|
||||
}
|
||||
|
||||
start() {
|
||||
super.start();
|
||||
}
|
||||
|
||||
end() {
|
||||
super.end();
|
||||
}
|
||||
}
|
||||
|
||||
export default MeasureCircle
|
||||
326
src/Measure/MeasureDistance/index.js
Normal file
326
src/Measure/MeasureDistance/index.js
Normal file
@ -0,0 +1,326 @@
|
||||
/**
|
||||
* @name: index
|
||||
* @author: Administrator
|
||||
* @date: 2022-07-11 10:31
|
||||
* @description:index
|
||||
* @update: 2022-07-11 10:31
|
||||
*/
|
||||
|
||||
import Measure from "../index"
|
||||
|
||||
class MeasureDistance extends Measure {
|
||||
/**
|
||||
* @constructor
|
||||
* @param sdk
|
||||
* @description 距离测量
|
||||
* */
|
||||
constructor(sdk, options = {}) {
|
||||
super(sdk, options)
|
||||
this.options.color = this.options.color || "#00ffff"
|
||||
this.start_id = ""
|
||||
this.end_id = ""
|
||||
this.polyline_id = ""
|
||||
this.clampPositions = []
|
||||
}
|
||||
|
||||
async clampToGroundMeasure(meters, cb) {
|
||||
let positions = []
|
||||
this.ids.forEach((id, index) => {
|
||||
let p = this.viewer.entities.getById(id).position.getValue()
|
||||
positions.push(this.cartesian3Towgs84(p, this.viewer))
|
||||
})
|
||||
let res = this.chunkLine(positions, meters)
|
||||
let coordinates = []
|
||||
res.forEach((Feature, index) => {
|
||||
if (index === 0) {
|
||||
coordinates = [...Feature.geometry.coordinates]
|
||||
} else {
|
||||
coordinates.push(Feature.geometry.coordinates[1])
|
||||
}
|
||||
})
|
||||
let total = coordinates.length
|
||||
|
||||
for (const item of coordinates) {
|
||||
const index = coordinates.indexOf(item);
|
||||
let r = await this.getHeight({lng: item[0], lat: item[1], alt: 0}, index, total,)
|
||||
cb(null, r)
|
||||
}
|
||||
}
|
||||
|
||||
async computeDisByTowPoint(p1, p2) {
|
||||
let d = this.computeDistance([p1, p2])
|
||||
let meters = 10
|
||||
let createLabel = (distance) => {
|
||||
if(this._isDestroy) {
|
||||
return
|
||||
}
|
||||
let label = this.getLabel("贴地距离:" + Number(distance).toFixed(2) + "米")
|
||||
label.pixelOffset = new Cesium.Cartesian2(
|
||||
0, -(32)
|
||||
)
|
||||
this.ids.push(MeasureDistance.create_point(Cesium.Cartesian3.fromDegrees(p2.lng, p2.lat, p2.alt), {label: label}, this))
|
||||
}
|
||||
let start = async (meters) => {
|
||||
let res = this.chunkLine([p1, p2], meters)
|
||||
let coordinates = []
|
||||
res.forEach((Feature, index) => {
|
||||
if (index === 0) {
|
||||
coordinates = [...Feature.geometry.coordinates]
|
||||
} else {
|
||||
coordinates.push(Feature.geometry.coordinates[1])
|
||||
}
|
||||
})
|
||||
let arr = []
|
||||
for (const item of coordinates) {
|
||||
const index = coordinates.indexOf(item);
|
||||
let r = await this.sampleHeight({lng: item[0], lat: item[1], alt: 0}, index)
|
||||
arr.push(r)
|
||||
}
|
||||
let total_length = 0
|
||||
let l = arr.length - 1
|
||||
arr.forEach((item, index) => {
|
||||
if (index !== l) {
|
||||
let d1 = this.computeDistance([item.position, arr[index + 1].position])
|
||||
let d2 = Math.abs(item.position.alt - arr[index + 1].position.alt)
|
||||
let d3 = Math.sqrt(d1 * d1 + d2 * d2)
|
||||
total_length += d3
|
||||
}
|
||||
})
|
||||
createLabel(total_length)
|
||||
}
|
||||
|
||||
|
||||
//暂时固定取20个点
|
||||
if (d > 20) {//大于20m时,固定取20个点
|
||||
meters = d / 20
|
||||
await start(meters)
|
||||
} else if (d < 1) {
|
||||
//不计算
|
||||
createLabel(d)
|
||||
} else {//小于20m的时候
|
||||
meters = 1
|
||||
await start(meters)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
async sampleHeight(p1, index) {
|
||||
let p2 = await this.sampleHeightMostDetailed([p1])
|
||||
p1.alt = p2[0].height
|
||||
return {position: p1, index}
|
||||
}
|
||||
|
||||
|
||||
async getHeight(p1, index, total) {
|
||||
let p2 = await this.sampleHeightMostDetailed([p1])
|
||||
p1.alt = p2[0].height
|
||||
this.clampPositions.push({position: p1, index})
|
||||
if (total === this.clampPositions.length) {
|
||||
let total_length = this.startCompute()
|
||||
return {total, current: this.clampPositions.length, total_length}
|
||||
}
|
||||
return {total, current: this.clampPositions.length,}
|
||||
}
|
||||
|
||||
startCompute() {
|
||||
this.clampPositions.sort(function (a, b) {
|
||||
return a.index < b.index
|
||||
})
|
||||
let total_length = 0
|
||||
let l = this.clampPositions.length - 1
|
||||
this.clampPositions.forEach((item, index) => {
|
||||
if (index !== l) {
|
||||
let d1 = this.computeDistance([item.position, this.clampPositions[index + 1].position])
|
||||
let d2 = Math.abs(item.position.alt - this.clampPositions[index + 1].position.alt)
|
||||
let d3 = Math.sqrt(d1 * d1 + d2 * d2)
|
||||
total_length += d3
|
||||
}
|
||||
})
|
||||
return Number(total_length.toFixed(2))
|
||||
}
|
||||
|
||||
|
||||
static createPolyline(that) {
|
||||
let id = that.randomString()
|
||||
that.viewer.entities.add(new Cesium.Entity({
|
||||
id,
|
||||
polyline: {
|
||||
positions: new Cesium.CallbackProperty(() => {
|
||||
return that.positions
|
||||
}, false),
|
||||
clampToGround: true,
|
||||
width: 3,
|
||||
material: new Cesium.PolylineDashMaterialProperty({
|
||||
color: new Cesium.Color.fromCssColorString(that.options.color || that.defaultColor),
|
||||
dashLength: 20, //短划线长度
|
||||
}),
|
||||
zIndex: 99999999
|
||||
}
|
||||
}))
|
||||
return id
|
||||
}
|
||||
|
||||
static create_point(cartesian, {
|
||||
label, image = "point.png",
|
||||
width,
|
||||
height
|
||||
}, that) {
|
||||
let id = that.randomString()
|
||||
let p = that.cartesian3Towgs84(cartesian, that.viewer)
|
||||
if (label) {
|
||||
label.pixelOffset = new Cesium.Cartesian2(
|
||||
0, -(height || 32)
|
||||
)
|
||||
}
|
||||
that.viewer.entities.add(
|
||||
new Cesium.Entity({
|
||||
id: id,
|
||||
label,
|
||||
position: Cesium.Cartesian3.fromDegrees(p.lng, p.lat, p.alt),
|
||||
billboard: {
|
||||
image: that.getSourceRootPath() + '/img/' + image,
|
||||
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
||||
width,
|
||||
height
|
||||
}
|
||||
})
|
||||
)
|
||||
return id
|
||||
}
|
||||
|
||||
getLabel(text) {
|
||||
return {
|
||||
text: text || '',
|
||||
//标注文字描述
|
||||
font: '20px Microsoft YaHei',
|
||||
fillColor: Cesium.Color.fromCssColorString('#f1e605'),
|
||||
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
|
||||
//标注的遮挡距离设置为100则视角与标注的距离大于100米时会有遮挡
|
||||
// distanceDisplayCondition: this.distanceDisplayCondition,
|
||||
scale: 1,
|
||||
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
||||
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
||||
|
||||
// disableDepthTestDistance: this.disableDepthTestDistance,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始测量
|
||||
*/
|
||||
start() {
|
||||
if (!YJ.Measure.GetMeasureStatus()) {
|
||||
super.start()
|
||||
this.positions = []
|
||||
this.cachePositions = []
|
||||
|
||||
|
||||
let leftEvent = async (movement, car) => {
|
||||
if (this.ids.length === 0) {
|
||||
this.polyline_id = (MeasureDistance.createPolyline(this))
|
||||
this.start_id = MeasureDistance.create_point(car, {
|
||||
image: "start1.png", width: 30, height: 38, label: this.getLabel("")
|
||||
}, this)
|
||||
//创建起点
|
||||
}
|
||||
|
||||
this.tip.setPosition(car, movement.position.x, movement.position.y)
|
||||
this.positions = this.cachePositions.concat(car)
|
||||
|
||||
if (this.ids.length !== 0) {
|
||||
let cur_point = this.cartesian3Towgs84(car, this.viewer)
|
||||
let pre_p = this.cartesian3Towgs84(this.cachePositions[this.cachePositions.length - 1], this.viewer)
|
||||
this.cachePositions.push(car)
|
||||
await this.computeDisByTowPoint(pre_p, cur_point)
|
||||
} else {
|
||||
this.cachePositions.push(car)
|
||||
this.ids.push(MeasureDistance.create_point(car, {}, this))
|
||||
let startPoint = this.viewer.entities.getById(this.ids[0])
|
||||
if(startPoint) {
|
||||
startPoint.billboard.show = false
|
||||
}
|
||||
}
|
||||
}
|
||||
let rightEvent = (movement, car) => {
|
||||
if (this.cachePositions.length) {
|
||||
this.positions = this.cachePositions
|
||||
this.end_id = MeasureDistance.create_point(this.cachePositions[this.cachePositions.length - 1], {
|
||||
image: "end1.png",
|
||||
width: 30,
|
||||
height: 38,
|
||||
}, this)
|
||||
let endPoint = this.viewer.entities.getById(this.ids[this.ids.length-1])
|
||||
if(endPoint) {
|
||||
endPoint.billboard.show = false
|
||||
}
|
||||
}
|
||||
if (this.cachePositions.length < 2) {
|
||||
this.destroy()
|
||||
YJ.Measure.Measures.pop()//弹出测量实体
|
||||
}
|
||||
this.end()
|
||||
}
|
||||
this.event.mouse_left(leftEvent)
|
||||
this.event.mouse_move((movement, car) => {
|
||||
this.tip.setPosition(car, movement.endPosition.x, movement.endPosition.y)
|
||||
this.positions = this.cachePositions.concat(car)
|
||||
// if (this.cachePositions.length) {
|
||||
// let cur_point = this.cartesian3Towgs84(car, this.viewer)
|
||||
// let pre_p = this.cartesian3Towgs84(this.cachePositions[this.cachePositions.length - 1], this.viewer)
|
||||
// let cur_len = this.computeDistance([cur_point, pre_p])
|
||||
// let text = "当前投影距离:" + cur_len + " 米"
|
||||
// // this.tip.set_text(text)
|
||||
// }
|
||||
})
|
||||
this.event.mouse_right(rightEvent)
|
||||
|
||||
this.event.gesture_pinck_start((movement, cartesian) => {
|
||||
let startTime = new Date()
|
||||
let pos = {
|
||||
position: {
|
||||
x: (movement.position1.x + movement.position2.x) / 2,
|
||||
y: (movement.position1.y + movement.position2.y) / 2
|
||||
}
|
||||
}
|
||||
this.event.gesture_pinck_end(() => {
|
||||
let endTime = new Date()
|
||||
if (endTime - startTime >= 500) {
|
||||
// 长按取消
|
||||
rightEvent(pos, cartesian)
|
||||
}
|
||||
else {
|
||||
leftEvent(pos, cartesian)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除测量
|
||||
*/
|
||||
destroy() {
|
||||
[this.polyline_id, this.end_id, this.start_id, ...this.ids].forEach(id => {
|
||||
this.remove_entity(id)
|
||||
})
|
||||
super.destroy()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 结束测量
|
||||
*/
|
||||
end() {
|
||||
// YJ.Measure.SetMeasureStatus(false)
|
||||
// this.tip.destroy()
|
||||
// this.event.destroy()
|
||||
super.end()
|
||||
// this.setPickStatus(this.pickStatus.pick)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export default MeasureDistance
|
||||
327
src/Measure/MeasureDistance/index2.js
Normal file
327
src/Measure/MeasureDistance/index2.js
Normal file
@ -0,0 +1,327 @@
|
||||
/**
|
||||
* @name: index
|
||||
* @author: Administrator
|
||||
* @date: 2022-07-11 10:31
|
||||
* @description:index
|
||||
* @update: 2022-07-11 10:31
|
||||
*/
|
||||
|
||||
import Measure from "../index"
|
||||
|
||||
class MeasureDistance extends Measure {
|
||||
/**
|
||||
* @constructor
|
||||
* @param sdk
|
||||
* @description 距离测量
|
||||
* */
|
||||
constructor(sdk, options = {}) {
|
||||
super(sdk, options)
|
||||
this.start_id = ""
|
||||
this.end_id = ""
|
||||
this.polyline_id = ""
|
||||
this.clampPositions = []
|
||||
}
|
||||
|
||||
async clampToGroundMeasure(meters, cb) {
|
||||
let positions = []
|
||||
this.ids.forEach((id, index) => {
|
||||
let p = this.viewer.entities.getById(id).position.getValue()
|
||||
positions.push(this.cartesian3Towgs84(p, this.viewer))
|
||||
})
|
||||
let res = this.chunkLine(positions, meters)
|
||||
let coordinates = []
|
||||
res.forEach((Feature, index) => {
|
||||
if (index === 0) {
|
||||
coordinates = [...Feature.geometry.coordinates]
|
||||
} else {
|
||||
coordinates.push(Feature.geometry.coordinates[1])
|
||||
}
|
||||
})
|
||||
let total = coordinates.length
|
||||
|
||||
for (const item of coordinates) {
|
||||
const index = coordinates.indexOf(item);
|
||||
let r = await this.getHeight({lng: item[0], lat: item[1], alt: 0}, index, total,)
|
||||
cb(null, r)
|
||||
}
|
||||
}
|
||||
|
||||
async computeDisByTowPoint(p1, p2) {
|
||||
let d = this.computeDistance([p1, p2])
|
||||
let meters = 10
|
||||
let createLabel = (distance) => {
|
||||
let label = this.getLabel("贴地距离:" + distance.toFixed(2) + "米")
|
||||
label.pixelOffset = new Cesium.Cartesian2(
|
||||
0, -(84)
|
||||
)
|
||||
let id = this.randomString()
|
||||
this.viewer.entities.add(
|
||||
new Cesium.Entity({
|
||||
id: id,
|
||||
label,
|
||||
position: Cesium.Cartesian3.fromDegrees(p2.lng, p2.lat, p2.alt),
|
||||
})
|
||||
)
|
||||
this.ids.push(id)
|
||||
}
|
||||
let start = async (meters) => {
|
||||
let res = this.chunkLine([p1, p2], meters)
|
||||
let coordinates = []
|
||||
res.forEach((Feature, index) => {
|
||||
if (index === 0) {
|
||||
coordinates = [...Feature.geometry.coordinates]
|
||||
} else {
|
||||
coordinates.push(Feature.geometry.coordinates[1])
|
||||
}
|
||||
})
|
||||
let arr = []
|
||||
for (const item of coordinates) {
|
||||
const index = coordinates.indexOf(item);
|
||||
let r = await this.sampleHeight({lng: item[0], lat: item[1], alt: 0}, index)
|
||||
arr.push(r)
|
||||
}
|
||||
let total_length = 0
|
||||
let l = arr.length - 1
|
||||
arr.forEach((item, index) => {
|
||||
if (index !== l) {
|
||||
let d1 = this.computeDistance([item.position, arr[index + 1].position])
|
||||
let d2 = Math.abs(item.position.alt - arr[index + 1].position.alt)
|
||||
let d3 = Math.sqrt(d1 * d1 + d2 * d2)
|
||||
total_length += d3
|
||||
}
|
||||
})
|
||||
createLabel(total_length)
|
||||
}
|
||||
|
||||
|
||||
//暂时固定取20个点
|
||||
if (d > 20) {//大于20m时,固定取20个点
|
||||
meters = d / 20
|
||||
await start(meters)
|
||||
} else if (d < 1) {
|
||||
//不计算
|
||||
createLabel(d)
|
||||
} else {//小于20m的时候
|
||||
meters = 1
|
||||
await start(meters)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
async sampleHeight(p1, index) {
|
||||
let p2 = await this.sampleHeightMostDetailed([p1])
|
||||
p1.alt = p2[0].height
|
||||
return {position: p1, index}
|
||||
}
|
||||
|
||||
|
||||
async getHeight(p1, index, total) {
|
||||
let p2 = await this.sampleHeightMostDetailed([p1])
|
||||
p1.alt = p2[0].height
|
||||
this.clampPositions.push({position: p1, index})
|
||||
if (total === this.clampPositions.length) {
|
||||
let total_length = this.startCompute()
|
||||
return {total, current: this.clampPositions.length, total_length}
|
||||
}
|
||||
return {total, current: this.clampPositions.length,}
|
||||
}
|
||||
|
||||
startCompute() {
|
||||
this.clampPositions.sort(function (a, b) {
|
||||
return a.index < b.index
|
||||
})
|
||||
let total_length = 0
|
||||
let l = this.clampPositions.length - 1
|
||||
this.clampPositions.forEach((item, index) => {
|
||||
if (index !== l) {
|
||||
let d1 = this.computeDistance([item.position, this.clampPositions[index + 1].position])
|
||||
let d2 = Math.abs(item.position.alt - this.clampPositions[index + 1].position.alt)
|
||||
let d3 = Math.sqrt(d1 * d1 + d2 * d2)
|
||||
total_length += d3
|
||||
}
|
||||
})
|
||||
return Number(total_length.toFixed(2))
|
||||
}
|
||||
|
||||
|
||||
static createPolyline(that) {
|
||||
let id = that.randomString()
|
||||
that.viewer.entities.add(new Cesium.Entity({
|
||||
id,
|
||||
polyline: {
|
||||
positions: new Cesium.CallbackProperty(() => {
|
||||
return that.positions
|
||||
}, false),
|
||||
clampToGround: true,
|
||||
width: 5,
|
||||
material: new Cesium.Color.fromCssColorString(that.options.color || that.defaultColor),
|
||||
zIndex: 99999999
|
||||
}
|
||||
}))
|
||||
return id
|
||||
}
|
||||
|
||||
static create_point(cartesian, {
|
||||
label, image = "point.png",
|
||||
width,
|
||||
height
|
||||
}, that) {
|
||||
let id = that.randomString()
|
||||
let p = that.cartesian3Towgs84(cartesian, that.viewer)
|
||||
if (label) {
|
||||
label.pixelOffset = new Cesium.Cartesian2(
|
||||
0, -(height || 32)
|
||||
)
|
||||
}
|
||||
that.viewer.entities.add(
|
||||
new Cesium.Entity({
|
||||
id: id,
|
||||
label,
|
||||
position: Cesium.Cartesian3.fromDegrees(p.lng, p.lat, p.alt),
|
||||
billboard: {
|
||||
image: that.getSourceRootPath() + '/img/' + image,
|
||||
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
||||
width,
|
||||
height
|
||||
}
|
||||
})
|
||||
)
|
||||
return id
|
||||
}
|
||||
|
||||
getLabel(text) {
|
||||
return {
|
||||
text: text || '',
|
||||
//标注文字描述
|
||||
font: '20px Microsoft YaHei',
|
||||
fillColor: Cesium.Color.fromCssColorString('#f1e605'),
|
||||
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
|
||||
//标注的遮挡距离设置为100则视角与标注的距离大于100米时会有遮挡
|
||||
// distanceDisplayCondition: this.distanceDisplayCondition,
|
||||
scale: 1,
|
||||
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
||||
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
||||
|
||||
// disableDepthTestDistance: this.disableDepthTestDistance,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始测量
|
||||
*/
|
||||
start() {
|
||||
if (!YJ.Measure.GetMeasureStatus()) {
|
||||
super.start()
|
||||
this.positions = []
|
||||
this.cachePositions = []
|
||||
|
||||
|
||||
this.event.mouse_left(async (movement, car) => {
|
||||
if (this.ids.length === 0) {
|
||||
this.polyline_id = (MeasureDistance.createPolyline(this))
|
||||
this.start_id = MeasureDistance.create_point(car, {
|
||||
image: "start.png", width: 32, height: 32, label: this.getLabel("")
|
||||
}, this)
|
||||
//创建起点
|
||||
}
|
||||
|
||||
if (this.ids.length !== 0) {
|
||||
let cur_point = this.cartesian3Towgs84(car, this.viewer)
|
||||
let pre_p = this.cartesian3Towgs84(this.cachePositions[this.cachePositions.length - 1], this.viewer)
|
||||
let cur_len = this.computeDistance([cur_point, pre_p])
|
||||
let text = "投影距离:" + cur_len + " 米"
|
||||
this.ids.push(MeasureDistance.create_point(car, {label: this.getLabel(text)}, this))
|
||||
this.cachePositions.push(car)
|
||||
//计算坡度
|
||||
this.computeAngle(pre_p, cur_point)
|
||||
await this.computeDisByTowPoint(pre_p, cur_point)
|
||||
} else {
|
||||
this.cachePositions.push(car)
|
||||
this.ids.push(MeasureDistance.create_point(car, {}, this))
|
||||
}
|
||||
|
||||
})
|
||||
this.event.mouse_move((movement, car) => {
|
||||
this.tip.setPosition(car, movement.endPosition.x, movement.endPosition.y)
|
||||
this.positions = this.cachePositions.concat(car)
|
||||
if (this.cachePositions.length) {
|
||||
let cur_point = this.cartesian3Towgs84(car, this.viewer)
|
||||
let pre_p = this.cartesian3Towgs84(this.cachePositions[this.cachePositions.length - 1], this.viewer)
|
||||
let cur_len = this.computeDistance([cur_point, pre_p])
|
||||
let text = "当前投影距离:" + cur_len + " 米"
|
||||
this.tip.set_text(text)
|
||||
}
|
||||
})
|
||||
this.event.mouse_right((movement, car) => {
|
||||
if (this.cachePositions.length) {
|
||||
this.positions = this.cachePositions
|
||||
this.end_id = MeasureDistance.create_point(this.cachePositions[this.cachePositions.length - 1], {
|
||||
image: "end.png",
|
||||
width: 32,
|
||||
height: 32,
|
||||
}, this)
|
||||
}
|
||||
if (this.cachePositions.length === 0) {
|
||||
this.destroy()
|
||||
YJ.Measure.Measures.pop()//弹出测量实体
|
||||
}
|
||||
this.end()
|
||||
})
|
||||
this.event.mouse_right_keyboard_ctrl((movement, car) => {
|
||||
if (this.cachePositions.length) {
|
||||
this.cachePositions.pop()
|
||||
this.remove_entity(this.ids.pop())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
computeAngle(start, end) {
|
||||
let d1 = this.computeDistance([start, end])
|
||||
let d2 = Math.abs(start.alt - end.alt)
|
||||
let d3 = Math.sqrt(d1 * d1 + d2 * d2)
|
||||
let cosAlpha = d1 / d3
|
||||
let acos = Math.acos(cosAlpha)
|
||||
let angle = this.radiansToDegrees(acos)
|
||||
let label = this.getLabel("坡度:" + angle.toFixed(1) + "°")
|
||||
label.pixelOffset = new Cesium.Cartesian2(
|
||||
0, -(58)
|
||||
)
|
||||
let id = this.randomString()
|
||||
this.viewer.entities.add(
|
||||
new Cesium.Entity({
|
||||
id: id,
|
||||
label,
|
||||
position: Cesium.Cartesian3.fromDegrees(end.lng, end.lat, end.alt),
|
||||
})
|
||||
)
|
||||
this.ids.push(id)
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除测量
|
||||
*/
|
||||
destroy() {
|
||||
[this.polyline_id, this.end_id, this.start_id, ...this.ids].forEach(id => {
|
||||
this.remove_entity(id)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 结束测量
|
||||
*/
|
||||
end() {
|
||||
// YJ.Measure.SetMeasureStatus(false)
|
||||
// this.tip.destroy()
|
||||
// this.event.destroy()
|
||||
super.end()
|
||||
// this.setPickStatus(this.pickStatus.pick)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export default MeasureDistance
|
||||
197
src/Measure/MeasureHeight/index.js
Normal file
197
src/Measure/MeasureHeight/index.js
Normal file
@ -0,0 +1,197 @@
|
||||
/**
|
||||
* @name: index
|
||||
* @author: Administrator
|
||||
* @date: 2022-07-22 17:15
|
||||
* @description:index
|
||||
* @update: 2022-07-22 17:15
|
||||
*/
|
||||
import Measure from "../index";
|
||||
|
||||
class MeasureHeight extends Measure {
|
||||
/**
|
||||
* @constructor
|
||||
* @param sdk
|
||||
* @description 高度测量
|
||||
* */
|
||||
constructor(sdk) {
|
||||
super(sdk, {text: "左键开始,右键取消"});
|
||||
}
|
||||
|
||||
static create_polygon(that) {
|
||||
let id = that.randomString()
|
||||
let a = that.viewer.entities.add(new Cesium.Entity({
|
||||
id,
|
||||
billboard: {
|
||||
image: that.getSourceRootPath() + '/img/point.png',
|
||||
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
||||
color: Cesium.Color.WHITE.withAlpha(0.99)
|
||||
|
||||
},
|
||||
position: new Cesium.CallbackProperty(() => {
|
||||
return that.position
|
||||
}, false),
|
||||
label: {
|
||||
text: new Cesium.CallbackProperty(() => {
|
||||
return that.text
|
||||
}, false),
|
||||
scale: 1,
|
||||
// fillColor: Cesium.Color.RED,
|
||||
font: 'normal 20px MicroSoft YaHei',
|
||||
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
|
||||
pixelOffset: new Cesium.Cartesian2(0, -15),
|
||||
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
||||
|
||||
},
|
||||
polyline: {
|
||||
positions: new Cesium.CallbackProperty(e => {
|
||||
return that.positions;
|
||||
}, false),
|
||||
width: 2,
|
||||
material: Cesium.Color.YELLOW,
|
||||
zIndex: 99999999
|
||||
},
|
||||
ellipse: {
|
||||
height: new Cesium.CallbackProperty(() => {
|
||||
return that.height + that.firstpoint.alt;
|
||||
}, false),
|
||||
semiMinorAxis: new Cesium.CallbackProperty(e => {
|
||||
return that.circleRadius;
|
||||
}, false),
|
||||
semiMajorAxis: new Cesium.CallbackProperty(e => {
|
||||
return that.circleRadius;
|
||||
}, false),
|
||||
material: new Cesium.Color.fromCssColorString(that.defaultColor)
|
||||
|
||||
},
|
||||
}))
|
||||
return id
|
||||
}
|
||||
|
||||
static create_point(that, cartesian, option = {}) {
|
||||
let id = that.randomString()
|
||||
let p = that.cartesian3Towgs84(cartesian, that.viewer)
|
||||
let params = {
|
||||
id: id,
|
||||
position: Cesium.Cartesian3.fromDegrees(p.lng, p.lat, p.alt),
|
||||
billboard: {
|
||||
image: that.getSourceRootPath() + '/img/point.png',
|
||||
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
||||
color: Cesium.Color.WHITE.withAlpha(0.99)
|
||||
}
|
||||
}
|
||||
if (option.label) {
|
||||
params.label = {
|
||||
text: option.label.text,
|
||||
scale: 1,
|
||||
// fillColor: Cesium.Color.fromCssColorString("#06eee5"),
|
||||
font: 'normal 20px MicroSoft YaHei',
|
||||
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
|
||||
pixelOffset: new Cesium.Cartesian2(0, -15),
|
||||
}
|
||||
}
|
||||
that.viewer.entities.add(
|
||||
new Cesium.Entity(params)
|
||||
)
|
||||
return id
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始测量
|
||||
*/
|
||||
start() {
|
||||
if (!YJ.Measure.GetMeasureStatus()) {
|
||||
super.start()
|
||||
this.positions = []
|
||||
this.position = new Cesium.Cartesian3()
|
||||
this.height = 0
|
||||
this.text = ""
|
||||
this.circleRadius = 0
|
||||
let count = 0;
|
||||
this.firstpoint = null
|
||||
|
||||
let leftEvent = (movement, cartesian) => {
|
||||
if (this.firstpoint === null) {
|
||||
this.positions.push(cartesian)
|
||||
this.firstpoint = this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
this.ids.push(MeasureHeight.create_polygon(this))
|
||||
this.ids.push(MeasureHeight.create_point(this, cartesian))
|
||||
}
|
||||
count++
|
||||
this.tip.setPosition(cartesian, movement.position.x, movement.position.y)
|
||||
if (count === 2) {
|
||||
if (this.firstpoint) {
|
||||
let cur_point = this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
this.positions[1] = Cesium.Cartesian3.fromDegrees(this.firstpoint.lng, this.firstpoint.lat, cur_point.alt)
|
||||
this.positions[2] = cartesian
|
||||
this.position = this.positions[1]
|
||||
this.circleRadius = this.computeDistance([this.firstpoint, cur_point])
|
||||
this.height = Number((cur_point.alt - this.firstpoint.alt).toFixed(2))
|
||||
this.text = "相对高度:" + this.height + " 米"
|
||||
this.tip.set_text("左键完成,右键取消;半径:" + this.circleRadius + " 米")
|
||||
}
|
||||
this.ids.push(MeasureHeight.create_point(this, cartesian, {label: {text: "半径:" + this.circleRadius + " 米"}}))
|
||||
this.end()
|
||||
}
|
||||
}
|
||||
this.event.mouse_left(leftEvent)
|
||||
this.event.mouse_move((movement, cartesian) => {
|
||||
this.tip.setPosition(cartesian, movement.endPosition.x, movement.endPosition.y)
|
||||
if (this.firstpoint) {
|
||||
let cur_point = this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
this.positions[1] = Cesium.Cartesian3.fromDegrees(this.firstpoint.lng, this.firstpoint.lat, cur_point.alt)
|
||||
this.positions[2] = cartesian
|
||||
this.position = this.positions[1]
|
||||
this.circleRadius = this.computeDistance([this.firstpoint, cur_point])
|
||||
this.height = Number((cur_point.alt - this.firstpoint.alt).toFixed(2))
|
||||
this.text = "相对高度:" + this.height + " 米"
|
||||
this.tip.set_text("左键完成,右键取消;半径:" + this.circleRadius + " 米")
|
||||
}
|
||||
})
|
||||
this.event.mouse_right((movement, cartesian) => {
|
||||
this.end()
|
||||
this.destroy()
|
||||
})
|
||||
this.event.gesture_pinck_start((movement, cartesian) => {
|
||||
let startTime = new Date()
|
||||
let pos = {
|
||||
position: {
|
||||
x: (movement.position1.x + movement.position2.x) / 2,
|
||||
y: (movement.position1.y + movement.position2.y) / 2
|
||||
}
|
||||
}
|
||||
this.event.gesture_pinck_end(() => {
|
||||
let endTime = new Date()
|
||||
if (endTime - startTime >= 500) {
|
||||
// 长按取消
|
||||
this.end()
|
||||
this.destroy()
|
||||
}
|
||||
else {
|
||||
leftEvent(pos, cartesian)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 结束测量
|
||||
*/
|
||||
end() {
|
||||
super.end()
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除测量
|
||||
*/
|
||||
destroy() {
|
||||
super.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
export default MeasureHeight
|
||||
182
src/Measure/MeasureLocation/index.js
Normal file
182
src/Measure/MeasureLocation/index.js
Normal file
@ -0,0 +1,182 @@
|
||||
/**
|
||||
* @name: index
|
||||
* @author: Administrator
|
||||
* @date: 2022-07-22 16:13
|
||||
* @description:index
|
||||
* @update: 2022-07-22 16:13
|
||||
*/
|
||||
import Measure from "../index";
|
||||
import { Proj } from "../../Tools/proj";
|
||||
import { getCoordinateSystem } from "../../Global/global";
|
||||
|
||||
class MeasureLocation extends Measure {
|
||||
/**
|
||||
* @constructor
|
||||
* @param sdk
|
||||
* @description 坐标测量
|
||||
* */
|
||||
constructor(sdk) {
|
||||
super(sdk, {text: ""});
|
||||
this.defaultColor = "#f11515"
|
||||
this.locationID = this.randomString()
|
||||
this.position = new Cesium.Cartesian3()
|
||||
this.text = ""
|
||||
}
|
||||
|
||||
static createLocation(that) {
|
||||
that.viewer.entities.add(new Cesium.Entity({
|
||||
id: that.locationID,
|
||||
show: false,
|
||||
position: new Cesium.CallbackProperty(() => {
|
||||
return that.position
|
||||
}, false),
|
||||
label: {
|
||||
text: new Cesium.CallbackProperty(() => {
|
||||
return that.text
|
||||
}, false),
|
||||
//标注文字描述
|
||||
font: '22px Microsoft YaHei',
|
||||
|
||||
fillColor: new Cesium.Color.fromCssColorString(that.defaultColor),
|
||||
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
|
||||
//标注的遮挡距离设置为100则视角与标注的距离大于100米时会有遮挡
|
||||
// distanceDisplayCondition: this.distanceDisplayCondition,
|
||||
// scale: this.options.label.scale,
|
||||
horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
|
||||
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
||||
|
||||
pixelOffset: new Cesium.Cartesian2(
|
||||
-100,
|
||||
-50
|
||||
),
|
||||
// disableDepthTestDistance: this.disableDepthTestDistance,
|
||||
},
|
||||
billboard: {
|
||||
image: that.getSourceRootPath() + "/img/location.png",
|
||||
color: Cesium.Color.fromCssColorString(`rgba(255,255,255,0.99)`),
|
||||
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
||||
// scaleByDistance: new Cesium.NearFarScalar(
|
||||
// 2000,
|
||||
// 1,
|
||||
// 1000000,
|
||||
// 0
|
||||
// ),
|
||||
scale: 1,
|
||||
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
||||
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
width: 48,
|
||||
height: 48
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
static create_point(that) {
|
||||
let id = that.randomString()
|
||||
that.viewer.entities.add(
|
||||
new Cesium.Entity({
|
||||
id: id,
|
||||
position: new Cesium.CallbackProperty(() => {
|
||||
return that.position
|
||||
}, false),
|
||||
billboard: {
|
||||
image: that.getSourceRootPath() + '/img/point.png',
|
||||
color: Cesium.Color.fromCssColorString(`rgba(255,255,255,0.99)`),
|
||||
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
||||
color: Cesium.Color.WHITE.withAlpha(0.99)
|
||||
}
|
||||
})
|
||||
)
|
||||
return id
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始测量
|
||||
*/
|
||||
start() {
|
||||
if (!YJ.Measure.GetMeasureStatus()) {
|
||||
super.start()
|
||||
this.cache_id = MeasureLocation.create_point(this)
|
||||
MeasureLocation.createLocation(this)
|
||||
|
||||
let leftEvent = (movement, cartesian) => {
|
||||
this.position = cartesian
|
||||
let entity = this.viewer.entities.getById(this.locationID)
|
||||
if(entity) {
|
||||
entity.show = true
|
||||
}
|
||||
let p = this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
let coordinateSystem = getCoordinateSystem()
|
||||
if(coordinateSystem==='EPSG:4326') {
|
||||
this.text = `经度:${Number(p.lng.toFixed(8))}\n纬度:${Number(p.lat.toFixed(8))}\n海拔:${Number(p.alt.toFixed(2))}`
|
||||
}
|
||||
else {
|
||||
let result = this.convert([{x: p.lng, y: p.lat, z: p.alt}], 'EPSG:4326', coordinateSystem)
|
||||
this.text = `x:${Number(result.points[0].x.toFixed(8))}\ny:${Number(result.points[0].y.toFixed(8))}\nz:${Number(result.points[0].z.toFixed(2))}`
|
||||
}
|
||||
this.end()
|
||||
}
|
||||
this.event.mouse_left(leftEvent)
|
||||
this.event.mouse_right((movement, cartesian) => {
|
||||
this.destroy()
|
||||
this.end()
|
||||
})
|
||||
this.event.mouse_move((movement, cartesian) => {
|
||||
this.tip.setPosition(cartesian, movement.endPosition.x, movement.endPosition.y)
|
||||
let entity = this.viewer.entities.getById(this.locationID)
|
||||
if(entity) {
|
||||
entity.show = true
|
||||
}
|
||||
this.position = cartesian
|
||||
let p = this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
let coordinateSystem = getCoordinateSystem()
|
||||
if(coordinateSystem==='EPSG:4326') {
|
||||
this.text = `经度:${Number(p.lng.toFixed(8))}\n纬度:${Number(p.lat.toFixed(8))}\n海拔:${Number(p.alt.toFixed(2))}`
|
||||
}
|
||||
else {
|
||||
let result = this.convert([{x: p.lng, y: p.lat, z: p.alt}], 'EPSG:4326', coordinateSystem)
|
||||
this.text = `x:${Number(result.points[0].x.toFixed(8))}\ny:${Number(result.points[0].y.toFixed(8))}\nz:${Number(result.points[0].z.toFixed(2))}`
|
||||
}
|
||||
})
|
||||
this.event.gesture_pinck_start((movement, cartesian) => {
|
||||
let startTime = new Date()
|
||||
let pos = {
|
||||
position: {
|
||||
x: (movement.position1.x + movement.position2.x) / 2,
|
||||
y: (movement.position1.y + movement.position2.y) / 2
|
||||
}
|
||||
}
|
||||
this.event.gesture_pinck_end(() => {
|
||||
let endTime = new Date()
|
||||
if (endTime - startTime >= 500) {
|
||||
// 长按取消
|
||||
this.destroy()
|
||||
this.end()
|
||||
}
|
||||
else {
|
||||
leftEvent(pos, cartesian)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除测量
|
||||
*/
|
||||
destroy() {
|
||||
this.remove_entity(this.locationID)
|
||||
this.remove_entity(this.cache_id)
|
||||
super.destroy()
|
||||
}
|
||||
|
||||
/**
|
||||
* 结束测量
|
||||
*/
|
||||
end() {
|
||||
super.end()
|
||||
}
|
||||
}
|
||||
|
||||
export default MeasureLocation
|
||||
276
src/Measure/MeasureProjectionDistance/index.js
Normal file
276
src/Measure/MeasureProjectionDistance/index.js
Normal file
@ -0,0 +1,276 @@
|
||||
/**
|
||||
* @name: index
|
||||
* @author: Administrator
|
||||
* @date: 2022-07-11 10:31
|
||||
* @description:index
|
||||
* @update: 2022-07-11 10:31
|
||||
*/
|
||||
|
||||
import Measure from "../index"
|
||||
|
||||
class MeasureProjectionDistance extends Measure {
|
||||
/**
|
||||
* @constructor
|
||||
* @param sdk
|
||||
* @description 投影距离测量
|
||||
* */
|
||||
constructor(sdk, options = {}) {
|
||||
super(sdk, options)
|
||||
this.options.color = this.options.color || "#00ffff"
|
||||
this.start_id = ""
|
||||
this.end_id = ""
|
||||
this.polyline_id = ""
|
||||
this.clampPositions = []
|
||||
}
|
||||
|
||||
async clampToGroundMeasure(meters, cb) {
|
||||
let positions = []
|
||||
this.ids.forEach((id, index) => {
|
||||
let p = this.viewer.entities.getById(id).position.getValue()
|
||||
positions.push(this.cartesian3Towgs84(p, this.viewer))
|
||||
})
|
||||
let res = this.chunkLine(positions, meters)
|
||||
let coordinates = []
|
||||
res.forEach((Feature, index) => {
|
||||
if (index === 0) {
|
||||
coordinates = [...Feature.geometry.coordinates]
|
||||
} else {
|
||||
coordinates.push(Feature.geometry.coordinates[1])
|
||||
}
|
||||
})
|
||||
let total = coordinates.length
|
||||
|
||||
for (const item of coordinates) {
|
||||
const index = coordinates.indexOf(item);
|
||||
let r = await this.getHeight({lng: item[0], lat: item[1], alt: 0}, index, total,)
|
||||
cb(null, r)
|
||||
}
|
||||
}
|
||||
|
||||
async sampleHeight(p1, index) {
|
||||
let p2 = await this.sampleHeightMostDetailed([p1])
|
||||
p1.alt = p2[0].height
|
||||
return {position: p1, index}
|
||||
}
|
||||
|
||||
|
||||
async getHeight(p1, index, total) {
|
||||
let p2 = await this.sampleHeightMostDetailed([p1])
|
||||
p1.alt = p2[0].height
|
||||
this.clampPositions.push({position: p1, index})
|
||||
if (total === this.clampPositions.length) {
|
||||
let total_length = this.startCompute()
|
||||
return {total, current: this.clampPositions.length, total_length}
|
||||
}
|
||||
return {total, current: this.clampPositions.length,}
|
||||
}
|
||||
|
||||
startCompute() {
|
||||
this.clampPositions.sort(function (a, b) {
|
||||
return a.index < b.index
|
||||
})
|
||||
let total_length = 0
|
||||
let l = this.clampPositions.length - 1
|
||||
this.clampPositions.forEach((item, index) => {
|
||||
if (index !== l) {
|
||||
let d1 = this.computeDistance([item.position, this.clampPositions[index + 1].position])
|
||||
let d2 = Math.abs(item.position.alt - this.clampPositions[index + 1].position.alt)
|
||||
let d3 = Math.sqrt(d1 * d1 + d2 * d2)
|
||||
total_length += d3
|
||||
}
|
||||
})
|
||||
return Number(total_length.toFixed(2))
|
||||
}
|
||||
|
||||
|
||||
static createPolyline(that) {
|
||||
let id = that.randomString()
|
||||
that.viewer.entities.add(new Cesium.Entity({
|
||||
id,
|
||||
polyline: {
|
||||
positions: new Cesium.CallbackProperty(() => {
|
||||
return that.positions
|
||||
}, false),
|
||||
clampToGround: true,
|
||||
width: 3,
|
||||
material: new Cesium.PolylineDashMaterialProperty({
|
||||
color: new Cesium.Color.fromCssColorString(that.options.color || that.defaultColor),
|
||||
dashLength: 20, //短划线长度
|
||||
}),
|
||||
},
|
||||
zIndex: 99999999
|
||||
}))
|
||||
return id
|
||||
}
|
||||
|
||||
static create_point(cartesian, {
|
||||
label, image = "point.png",
|
||||
width,
|
||||
height
|
||||
}, that) {
|
||||
let id = that.randomString()
|
||||
let p = that.cartesian3Towgs84(cartesian, that.viewer)
|
||||
if (label) {
|
||||
label.pixelOffset = new Cesium.Cartesian2(
|
||||
0, -(height || 32)
|
||||
)
|
||||
}
|
||||
that.viewer.entities.add(
|
||||
new Cesium.Entity({
|
||||
id: id,
|
||||
label,
|
||||
position: Cesium.Cartesian3.fromDegrees(p.lng, p.lat, p.alt),
|
||||
billboard: {
|
||||
image: that.getSourceRootPath() + '/img/' + image,
|
||||
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
||||
width,
|
||||
height
|
||||
}
|
||||
})
|
||||
)
|
||||
return id
|
||||
}
|
||||
|
||||
getLabel(text) {
|
||||
return {
|
||||
text: text || '',
|
||||
//标注文字描述
|
||||
font: '20px Microsoft YaHei',
|
||||
fillColor: Cesium.Color.fromCssColorString('#f1e605'),
|
||||
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
|
||||
//标注的遮挡距离设置为100则视角与标注的距离大于100米时会有遮挡
|
||||
// distanceDisplayCondition: this.distanceDisplayCondition,
|
||||
scale: 1,
|
||||
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
||||
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
||||
|
||||
// disableDepthTestDistance: this.disableDepthTestDistance,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始测量
|
||||
*/
|
||||
start() {
|
||||
if (!YJ.Measure.GetMeasureStatus()) {
|
||||
super.start()
|
||||
this.positions = []
|
||||
this.cachePositions = []
|
||||
|
||||
let leftEvent = async (movement, car) => {
|
||||
if (this.ids.length === 0) {
|
||||
this.polyline_id = (MeasureProjectionDistance.createPolyline(this))
|
||||
this.start_id = MeasureProjectionDistance.create_point(car, {
|
||||
image: "start1.png", width: 30, height: 38, label: this.getLabel("")
|
||||
}, this)
|
||||
//创建起点
|
||||
}
|
||||
|
||||
this.positions = this.cachePositions.concat(car)
|
||||
this.tip.setPosition(car, movement.position.x, movement.position.y)
|
||||
|
||||
if (this.ids.length !== 0) {
|
||||
let cur_point = this.cartesian3Towgs84(car, this.viewer)
|
||||
let pre_p = this.cartesian3Towgs84(this.cachePositions[this.cachePositions.length - 1], this.viewer)
|
||||
let cur_len = this.computeDistance([cur_point, pre_p])
|
||||
let text = "投影距离:" + cur_len + " 米"
|
||||
this.ids.push(MeasureProjectionDistance.create_point(car, {label: this.getLabel(text)}, this))
|
||||
this.cachePositions.push(car)
|
||||
} else {
|
||||
this.cachePositions.push(car)
|
||||
this.ids.push(MeasureProjectionDistance.create_point(car, {show: false}, this))
|
||||
let startPoint = this.viewer.entities.getById(this.ids[0])
|
||||
if(startPoint) {
|
||||
startPoint.billboard.show = false
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
let rightEvent = (movement, car) => {
|
||||
if (this.cachePositions.length) {
|
||||
this.positions = this.cachePositions
|
||||
this.end_id = MeasureProjectionDistance.create_point(this.cachePositions[this.cachePositions.length - 1], {
|
||||
image: "end1.png",
|
||||
width: 30,
|
||||
height: 38,
|
||||
}, this)
|
||||
let endPoint = this.viewer.entities.getById(this.ids[this.ids.length-1])
|
||||
if(endPoint) {
|
||||
endPoint.billboard.show = false
|
||||
}
|
||||
}
|
||||
if (this.cachePositions.length < 2) {
|
||||
this.destroy()
|
||||
YJ.Measure.Measures.pop()//弹出测量实体
|
||||
}
|
||||
this.end()
|
||||
}
|
||||
|
||||
this.event.mouse_left(leftEvent)
|
||||
this.event.mouse_move((movement, car) => {
|
||||
this.tip.setPosition(car, movement.endPosition.x, movement.endPosition.y)
|
||||
this.positions = this.cachePositions.concat(car)
|
||||
if (this.cachePositions.length) {
|
||||
let cur_point = this.cartesian3Towgs84(car, this.viewer)
|
||||
let pre_p = this.cartesian3Towgs84(this.cachePositions[this.cachePositions.length - 1], this.viewer)
|
||||
let cur_len = this.computeDistance([cur_point, pre_p])
|
||||
let text = "当前投影距离:" + cur_len + " 米"
|
||||
this.tip.set_text(text)
|
||||
}
|
||||
})
|
||||
this.event.mouse_right(rightEvent)
|
||||
this.event.mouse_right_keyboard_ctrl((movement, car) => {
|
||||
if (this.cachePositions.length) {
|
||||
this.cachePositions.pop()
|
||||
this.remove_entity(this.ids.pop())
|
||||
}
|
||||
})
|
||||
this.event.gesture_pinck_start((movement, cartesian) => {
|
||||
let startTime = new Date()
|
||||
let pos = {
|
||||
position: {
|
||||
x: (movement.position1.x + movement.position2.x) / 2,
|
||||
y: (movement.position1.y + movement.position2.y) / 2
|
||||
}
|
||||
}
|
||||
this.event.gesture_pinck_end(() => {
|
||||
let endTime = new Date()
|
||||
if (endTime - startTime >= 500) {
|
||||
// 长按取消
|
||||
rightEvent(pos, cartesian)
|
||||
}
|
||||
else {
|
||||
leftEvent(pos, cartesian)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除测量
|
||||
*/
|
||||
destroy() {
|
||||
[this.polyline_id, this.end_id, this.start_id, ...this.ids].forEach(id => {
|
||||
this.remove_entity(id)
|
||||
})
|
||||
super.destroy()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 结束测量
|
||||
*/
|
||||
end() {
|
||||
// YJ.Measure.SetMeasureStatus(false)
|
||||
// this.tip.destroy()
|
||||
// this.event.destroy()
|
||||
super.end()
|
||||
// this.setPickStatus(this.pickStatus.pick)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export default MeasureProjectionDistance
|
||||
316
src/Measure/MeasureSlopeDistance/index.js
Normal file
316
src/Measure/MeasureSlopeDistance/index.js
Normal file
@ -0,0 +1,316 @@
|
||||
/**
|
||||
* @name: index
|
||||
* @author: Administrator
|
||||
* @date: 2022-07-11 10:31
|
||||
* @description:index
|
||||
* @update: 2022-07-11 10:31
|
||||
*/
|
||||
|
||||
import Measure from "../index"
|
||||
import MouseEvent from "../../Event";
|
||||
|
||||
class MeasureSlopeDistance extends Measure {
|
||||
/**
|
||||
* @constructor
|
||||
* @param sdk
|
||||
* @description 坡度测量
|
||||
* */
|
||||
constructor(sdk, options = {}) {
|
||||
super(sdk, options)
|
||||
this.options.color = this.options.color || "#00ffff"
|
||||
this.start_id = ""
|
||||
this.end_id = ""
|
||||
this.polyline_id = ""
|
||||
this.clampPositions = []
|
||||
this.event = new MouseEvent(sdk)
|
||||
}
|
||||
|
||||
async clampToGroundMeasure(meters, cb) {
|
||||
let positions = []
|
||||
this.ids.forEach((id, index) => {
|
||||
let p = this.viewer.entities.getById(id).position.getValue()
|
||||
positions.push(this.cartesian3Towgs84(p, this.viewer))
|
||||
})
|
||||
let res = this.chunkLine(positions, meters)
|
||||
let coordinates = []
|
||||
res.forEach((Feature, index) => {
|
||||
if (index === 0) {
|
||||
coordinates = [...Feature.geometry.coordinates]
|
||||
} else {
|
||||
coordinates.push(Feature.geometry.coordinates[1])
|
||||
}
|
||||
})
|
||||
let total = coordinates.length
|
||||
|
||||
for (const item of coordinates) {
|
||||
const index = coordinates.indexOf(item);
|
||||
let r = await this.getHeight({ lng: item[0], lat: item[1], alt: 0 }, index, total,)
|
||||
cb(null, r)
|
||||
}
|
||||
}
|
||||
|
||||
async sampleHeight(p1, index) {
|
||||
let p2 = await this.sampleHeightMostDetailed([p1])
|
||||
p1.alt = p2[0].height
|
||||
return { position: p1, index }
|
||||
}
|
||||
|
||||
|
||||
async getHeight(p1, index, total) {
|
||||
let p2 = await this.sampleHeightMostDetailed([p1])
|
||||
p1.alt = p2[0].height
|
||||
this.clampPositions.push({ position: p1, index })
|
||||
if (total === this.clampPositions.length) {
|
||||
let total_length = this.startCompute()
|
||||
return { total, current: this.clampPositions.length, total_length }
|
||||
}
|
||||
return { total, current: this.clampPositions.length, }
|
||||
}
|
||||
|
||||
startCompute() {
|
||||
this.clampPositions.sort(function (a, b) {
|
||||
return a.index < b.index
|
||||
})
|
||||
let total_length = 0
|
||||
let l = this.clampPositions.length - 1
|
||||
this.clampPositions.forEach((item, index) => {
|
||||
if (index !== l) {
|
||||
let d1 = this.computeDistance([item.position, this.clampPositions[index + 1].position])
|
||||
let d2 = Math.abs(item.position.alt - this.clampPositions[index + 1].position.alt)
|
||||
let d3 = Math.sqrt(d1 * d1 + d2 * d2)
|
||||
total_length += d3
|
||||
}
|
||||
})
|
||||
return Number(total_length.toFixed(2))
|
||||
}
|
||||
|
||||
|
||||
static createPolyline(that) {
|
||||
let id = that.randomString()
|
||||
that.viewer.entities.add(new Cesium.Entity({
|
||||
id,
|
||||
polyline: {
|
||||
positions: new Cesium.CallbackProperty(() => {
|
||||
return that.positions
|
||||
}, false),
|
||||
clampToGround: true,
|
||||
width: 3,
|
||||
material: new Cesium.PolylineDashMaterialProperty({
|
||||
color: new Cesium.Color.fromCssColorString(that.options.color || that.defaultColor),
|
||||
dashLength: 20, //短划线长度
|
||||
}),
|
||||
zIndex: 99999999
|
||||
}
|
||||
}))
|
||||
return id
|
||||
}
|
||||
|
||||
static create_point(cartesian, {
|
||||
label, image = "point.png",
|
||||
width,
|
||||
height
|
||||
}, that) {
|
||||
let id = that.randomString()
|
||||
let p = that.cartesian3Towgs84(cartesian, that.viewer)
|
||||
if (label) {
|
||||
label.pixelOffset = new Cesium.Cartesian2(
|
||||
0, -(height || 32)
|
||||
)
|
||||
}
|
||||
that.viewer.entities.add(
|
||||
new Cesium.Entity({
|
||||
id: id,
|
||||
label,
|
||||
position: Cesium.Cartesian3.fromDegrees(p.lng, p.lat, p.alt),
|
||||
billboard: {
|
||||
image: that.getSourceRootPath() + '/img/' + image,
|
||||
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
||||
width,
|
||||
height
|
||||
}
|
||||
})
|
||||
)
|
||||
return id
|
||||
}
|
||||
|
||||
getLabel(text) {
|
||||
return {
|
||||
text: text || '',
|
||||
//标注文字描述
|
||||
font: '20px Microsoft YaHei',
|
||||
fillColor: Cesium.Color.fromCssColorString('#f1e605'),
|
||||
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
|
||||
//标注的遮挡距离设置为100则视角与标注的距离大于100米时会有遮挡
|
||||
// distanceDisplayCondition: this.distanceDisplayCondition,
|
||||
scale: 1,
|
||||
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
||||
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
||||
|
||||
// disableDepthTestDistance: this.disableDepthTestDistance,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始测量
|
||||
*/
|
||||
start() {
|
||||
if (!YJ.Measure.GetMeasureStatus()) {
|
||||
super.start()
|
||||
this.positions = []
|
||||
this.cachePositions = []
|
||||
|
||||
let leftEvent = (movement, car) => {
|
||||
if (this.ids.length === 0) {
|
||||
this.polyline_id = (MeasureSlopeDistance.createPolyline(this))
|
||||
this.start_id = MeasureSlopeDistance.create_point(car, {
|
||||
image: "start1.png", width: 30, height: 38, label: this.getLabel("")
|
||||
}, this)
|
||||
//创建起点
|
||||
}
|
||||
this.tip.setPosition(car, movement.position.x, movement.position.y)
|
||||
this.positions = this.cachePositions.concat(car)
|
||||
if (this.ids.length !== 0) {
|
||||
let cur_point = this.cartesian3Towgs84(car, this.viewer)
|
||||
let pre_p = this.cartesian3Towgs84(this.cachePositions[this.cachePositions.length - 1], this.viewer)
|
||||
if (cur_point.lng !== pre_p.lng || cur_point.lat !== pre_p.lat || cur_point.alt !== pre_p.alt) {
|
||||
this.cachePositions.push(car)
|
||||
//计算坡度
|
||||
this.computeAngle(pre_p, cur_point)
|
||||
}
|
||||
} else {
|
||||
this.cachePositions.push(car)
|
||||
this.ids.push(MeasureSlopeDistance.create_point(car, {}, this))
|
||||
let startPoint = this.viewer.entities.getById(this.ids[0])
|
||||
if(startPoint) {
|
||||
startPoint.billboard.show = false
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
let rightEvent = (movement, car) => {
|
||||
if (this.ids.length !== 0) {
|
||||
// let cur_point = this.cartesian3Towgs84(car, this.viewer)
|
||||
// let pre_p = this.cartesian3Towgs84(this.cachePositions[this.cachePositions.length - 1], this.viewer)
|
||||
// if (cur_point.lng !== pre_p.lng || cur_point.lat !== pre_p.lat || cur_point.alt !== pre_p.alt) {
|
||||
// this.cachePositions.push(car)
|
||||
// //计算坡度
|
||||
// this.computeAngle(pre_p, cur_point)
|
||||
// }
|
||||
} else {
|
||||
// this.cachePositions.push(car)
|
||||
this.ids.push(MeasureSlopeDistance.create_point(car, {}, this))
|
||||
}
|
||||
if (this.cachePositions.length) {
|
||||
this.positions = this.cachePositions
|
||||
this.end_id = MeasureSlopeDistance.create_point(this.cachePositions[this.cachePositions.length - 1], {
|
||||
image: "end1.png",
|
||||
width: 30,
|
||||
height: 38,
|
||||
}, this)
|
||||
let endPoint = this.viewer.entities.getById(this.ids[this.ids.length-1])
|
||||
if(endPoint) {
|
||||
endPoint.billboard.show = false
|
||||
}
|
||||
}
|
||||
if (this.cachePositions.length < 2) {
|
||||
this.destroy()
|
||||
YJ.Measure.Measures.pop()//弹出测量实体
|
||||
}
|
||||
this.end()
|
||||
}
|
||||
|
||||
this.event.mouse_left(leftEvent)
|
||||
this.event.mouse_move((movement, car) => {
|
||||
movement.endPosition.y += 2
|
||||
let position = movement.endPosition
|
||||
let cartesian = this.viewer.scene.pickPosition(position)
|
||||
if (!cartesian) {
|
||||
const ray = this.viewer.camera.getPickRay(position); //相交的射线
|
||||
cartesian = this.viewer.scene.globe.pick(ray, this.viewer.scene);
|
||||
}
|
||||
this.tip.setPosition(car, movement.endPosition.x, movement.endPosition.y)
|
||||
this.positions = this.cachePositions.concat(cartesian)
|
||||
if (this.cachePositions.length) {
|
||||
let cur_point = this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
let pre_p = this.cartesian3Towgs84(this.cachePositions[this.cachePositions.length - 1], this.viewer)
|
||||
let d1 = this.computeDistance([pre_p, cur_point])
|
||||
let d2 = Math.abs(pre_p.alt - cur_point.alt)
|
||||
let d3 = Math.sqrt(d1 * d1 + d2 * d2)
|
||||
let cosAlpha = d1 / d3
|
||||
let acos = Math.acos(cosAlpha)
|
||||
let angle = this.radiansToDegrees(acos)
|
||||
let label = "坡度:" + angle.toFixed(2) + "°"
|
||||
this.tip.set_text(label)
|
||||
}
|
||||
})
|
||||
this.event.mouse_right(rightEvent)
|
||||
this.event.mouse_right_keyboard_ctrl((movement, car) => {
|
||||
if (this.cachePositions.length) {
|
||||
this.cachePositions.pop()
|
||||
this.remove_entity(this.ids.pop())
|
||||
}
|
||||
})
|
||||
|
||||
this.event.gesture_pinck_start((movement, cartesian) => {
|
||||
let startTime = new Date()
|
||||
let pos = {
|
||||
position: {
|
||||
x: (movement.position1.x + movement.position2.x) / 2,
|
||||
y: (movement.position1.y + movement.position2.y) / 2
|
||||
}
|
||||
}
|
||||
this.event.gesture_pinck_end(() => {
|
||||
let endTime = new Date()
|
||||
if (endTime - startTime >= 500) {
|
||||
// 长按取消
|
||||
rightEvent(pos, cartesian)
|
||||
}
|
||||
else {
|
||||
leftEvent(pos, cartesian)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
computeAngle(start, end) {
|
||||
let d1 = this.computeDistance([start, end])
|
||||
let d2 = Math.abs(start.alt - end.alt)
|
||||
let d3 = Math.sqrt(d1 * d1 + d2 * d2)
|
||||
let cosAlpha = d1 / d3
|
||||
let acos = Math.acos(cosAlpha)
|
||||
let angle = this.radiansToDegrees(acos)
|
||||
let label = this.getLabel("坡度:" + angle.toFixed(2) + "°")
|
||||
label.pixelOffset = new Cesium.Cartesian2(
|
||||
0, -(32)
|
||||
)
|
||||
this.ids.push(MeasureSlopeDistance.create_point(Cesium.Cartesian3.fromDegrees(end.lng, end.lat, end.alt), {label: label}, this))
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除测量
|
||||
*/
|
||||
destroy() {
|
||||
[this.polyline_id, this.end_id, this.start_id, ...this.ids].forEach(id => {
|
||||
this.remove_entity(id)
|
||||
})
|
||||
super.destroy()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 结束测量
|
||||
*/
|
||||
end() {
|
||||
// YJ.Measure.SetMeasureStatus(false)
|
||||
// this.tip.destroy()
|
||||
// this.event.destroy()
|
||||
super.end()
|
||||
// this.setPickStatus(this.pickStatus.pick)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export default MeasureSlopeDistance
|
||||
173
src/Measure/MeasureTdArea/index.js
Normal file
173
src/Measure/MeasureTdArea/index.js
Normal file
@ -0,0 +1,173 @@
|
||||
import Measure from "../index"
|
||||
|
||||
/**@extends Measure*/
|
||||
class MeasureTdArea extends Measure {
|
||||
/**
|
||||
* @constructor
|
||||
* @param sdk
|
||||
* @description 贴地面积测量
|
||||
* */
|
||||
constructor(sdk, options = {}) {
|
||||
super(sdk, options);
|
||||
this.options.lineColor = '#ffdf53'
|
||||
this.polygon_id = ""
|
||||
}
|
||||
|
||||
static create_polygon(that) {
|
||||
let id = that.randomString()
|
||||
|
||||
let scaleByDistance = new Cesium.NearFarScalar(2000, 1, 100000, 0)
|
||||
|
||||
let e = that.viewer.entities.add(
|
||||
new Cesium.Entity({
|
||||
id: id,
|
||||
label: {
|
||||
text: new Cesium.CallbackProperty(() => {
|
||||
return that.text
|
||||
}, false),
|
||||
//标注文字描述
|
||||
font: '20px Microsoft YaHei',
|
||||
fillColor: Cesium.Color.fromCssColorString('#ffffff'),
|
||||
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
|
||||
//标注的遮挡距离设置为100则视角与标注的距离大于100米时会有遮挡
|
||||
// distanceDisplayCondition: this.distanceDisplayCondition,
|
||||
|
||||
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
||||
|
||||
// scaleByDistance,
|
||||
scale: 1,
|
||||
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
||||
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
},
|
||||
position: new Cesium.CallbackProperty(() => {
|
||||
return that.center
|
||||
}, false),
|
||||
polygon: {
|
||||
classificationType: Cesium.ClassificationType.BOTH,
|
||||
hierarchy: new Cesium.CallbackProperty((e) => {
|
||||
return new Cesium.PolygonHierarchy(that.positions)
|
||||
}, false),
|
||||
material: new Cesium.Color.fromCssColorString(that.options.color || that.defaultColor),
|
||||
zIndex: 99999999
|
||||
},
|
||||
polyline: {
|
||||
positions: new Cesium.CallbackProperty(() => {
|
||||
if (that.positions.length)
|
||||
return that.positions.concat(that.positions[0])
|
||||
return that.positions
|
||||
}, false),
|
||||
width: 2,
|
||||
material: new Cesium.PolylineDashMaterialProperty({
|
||||
color: new Cesium.Color.fromCssColorString(that.options.lineColor || that.defaultColor),
|
||||
dashLength: 20, //短划线长度
|
||||
}),
|
||||
clampToGround: true,
|
||||
zIndex: 99999999
|
||||
}
|
||||
})
|
||||
)
|
||||
return id
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始测量
|
||||
*/
|
||||
start() {
|
||||
if (!YJ.Measure.GetMeasureStatus()) {
|
||||
super.start()
|
||||
this.ids = []
|
||||
this.positions = []
|
||||
this.text = ""
|
||||
this.center = new Cesium.Cartesian3()
|
||||
this.cachePositions = []
|
||||
let height = 0
|
||||
let text
|
||||
|
||||
let leftEvent = (movement, car) => {
|
||||
if (this.ids.length === 0) {
|
||||
this.polygon_id = MeasureTdArea.create_polygon(this)
|
||||
}
|
||||
this.cachePositions.push({ ...car })
|
||||
this.ids.push(this.create_point({ ...car }, false))
|
||||
let po = this.cartesian3Towgs84({ ...car }, this.viewer)
|
||||
if (po.alt > height) {
|
||||
height = po.alt
|
||||
}
|
||||
|
||||
this.positions = this.cachePositions.concat({ ...car })
|
||||
this.tip.setPosition({ ...car }, movement.position.x, movement.position.y)
|
||||
}
|
||||
let rightEvent = (movement, car) => {
|
||||
this.positions = this.cachePositions
|
||||
if (this.positions.length > 2) {
|
||||
let arr = []
|
||||
this.positions.forEach(item => {
|
||||
let p = this.cartesian3Towgs84(item, this.viewer)
|
||||
arr.push({ lng: p.lng, lat: p.lat })
|
||||
})
|
||||
setTimeout(() => {
|
||||
let center = this.computeCenter(arr)
|
||||
let area = this.computeSignedArea(this.viewer, arr)
|
||||
this.center = new Cesium.Cartesian3.fromDegrees(center.lng, center.lat, height)
|
||||
this.text = "贴地面积:" + area + " ㎡"
|
||||
}, 0);
|
||||
}
|
||||
else {
|
||||
let error = '面积计算至少需要三个坐标!'
|
||||
console.warn(error)
|
||||
window.ELEMENT && window.ELEMENT.Message({
|
||||
message: error,
|
||||
type: 'warning',
|
||||
duration: 1500
|
||||
});
|
||||
this.destroy()
|
||||
}
|
||||
this.end()
|
||||
}
|
||||
this.event.mouse_left(leftEvent)
|
||||
this.event.mouse_move((movement, car) => {
|
||||
this.tip.setPosition({ ...car }, movement.endPosition.x, movement.endPosition.y)
|
||||
this.positions = this.cachePositions.concat({ ...car })
|
||||
})
|
||||
this.event.mouse_right(rightEvent)
|
||||
this.event.gesture_pinck_start((movement, cartesian) => {
|
||||
let startTime = new Date()
|
||||
let pos = {
|
||||
position: {
|
||||
x: (movement.position1.x + movement.position2.x) / 2,
|
||||
y: (movement.position1.y + movement.position2.y) / 2
|
||||
}
|
||||
}
|
||||
this.event.gesture_pinck_end(() => {
|
||||
let endTime = new Date()
|
||||
if (endTime - startTime >= 500) {
|
||||
// 长按取消
|
||||
rightEvent(pos, cartesian)
|
||||
}
|
||||
else {
|
||||
leftEvent(pos, cartesian)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除测量
|
||||
*/
|
||||
destroy() {
|
||||
[this.polygon_id, ...this.ids].forEach(id => {
|
||||
this.remove_entity(id)
|
||||
})
|
||||
super.destroy()
|
||||
}
|
||||
|
||||
/**
|
||||
* 结束测量
|
||||
*/
|
||||
end() {
|
||||
super.end()
|
||||
}
|
||||
}
|
||||
|
||||
export default MeasureTdArea
|
||||
290
src/Measure/MeasureTriangle/index.js
Normal file
290
src/Measure/MeasureTriangle/index.js
Normal file
@ -0,0 +1,290 @@
|
||||
/**
|
||||
* @name: index
|
||||
* @author: Administrator
|
||||
* @date: 2022-07-21 15:22
|
||||
* @description:index
|
||||
* @update: 2022-07-21 15:22
|
||||
*/
|
||||
import Measure from "../index";
|
||||
|
||||
class MeasureTriangle extends Measure {
|
||||
/**
|
||||
* @constructor
|
||||
* @param sdk
|
||||
* @description 三角测量
|
||||
* */
|
||||
constructor(sdk) {
|
||||
super(sdk);
|
||||
}
|
||||
|
||||
cal_center(positions) {
|
||||
let p1 = this.cartesian3Towgs84(positions[0], this.viewer)
|
||||
let p2 = this.cartesian3Towgs84(positions[1], this.viewer)
|
||||
let center = this.computeCenter([p1, p2]);
|
||||
return Cesium.Cartesian3.fromDegrees(center.lng, center.lat, (p1.alt + p2.alt) / 2)
|
||||
}
|
||||
|
||||
cal_distance(positions) {
|
||||
let p1 = this.cartesian3Towgs84(positions[0], this.viewer)
|
||||
let p2 = this.cartesian3Towgs84(positions[1], this.viewer)
|
||||
let dis = this.computeDistance([p1, p2])
|
||||
p1.alt = p1.alt.toFixed(2)
|
||||
p2.alt = p2.alt.toFixed(2)
|
||||
if (p1.alt === p2.alt) {//水平边
|
||||
return dis
|
||||
} else if (Number(dis) === 0.00) {//竖直边
|
||||
return Math.abs(p1.alt - p2.alt).toFixed(2)
|
||||
} else {//斜边
|
||||
return Math.sqrt(dis * dis + Math.pow(Math.abs(p1.alt - p2.alt).toFixed(2), 2)).toFixed(2)
|
||||
}
|
||||
}
|
||||
|
||||
createPolyline(id) {
|
||||
let obj = this.id_map.get(id)
|
||||
|
||||
this.viewer.entities.add(new Cesium.Entity({
|
||||
id,
|
||||
position: new Cesium.CallbackProperty(() => {
|
||||
if (obj.positions.length === 2)
|
||||
return this.cal_center(obj.positions)
|
||||
else
|
||||
return Cesium.Cartesian3()
|
||||
}, false),
|
||||
label: {
|
||||
text: new Cesium.CallbackProperty(() => {
|
||||
if (obj.positions.length === 2)
|
||||
return this.cal_distance(obj.positions) + "米"
|
||||
else
|
||||
return "0米"
|
||||
}, false),
|
||||
scale: 1,
|
||||
fillColor: Cesium.Color.RED,
|
||||
font: 'normal 20px MicroSoft YaHei',
|
||||
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
|
||||
pixelOffset: new Cesium.Cartesian2(0, -10),
|
||||
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
||||
|
||||
},
|
||||
polyline: {
|
||||
positions: new Cesium.CallbackProperty(() => {
|
||||
return obj.positions
|
||||
}, false),
|
||||
width: 2,
|
||||
material: Cesium.Color.YELLOW,
|
||||
zIndex: 99999999
|
||||
}
|
||||
}))
|
||||
|
||||
this.ids.push(id)
|
||||
}
|
||||
|
||||
create_angle_label(positions1, positions2, id, type) {
|
||||
let entity = new Cesium.Entity({
|
||||
id,
|
||||
position: new Cesium.CallbackProperty(() => {
|
||||
if (positions1.length === 2)
|
||||
return this.cal_point(positions1, positions2)
|
||||
else
|
||||
return Cesium.Cartesian3()
|
||||
}),
|
||||
label: {
|
||||
text: new Cesium.CallbackProperty(() => {
|
||||
if (positions1.length === 2)
|
||||
return this.cal_angle(positions1, positions2, type) + "°"
|
||||
else
|
||||
return "0°"
|
||||
}, false),
|
||||
scale: 1,
|
||||
fillColor: Cesium.Color.RED,
|
||||
font: 'normal 20px MicroSoft YaHei',
|
||||
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
|
||||
pixelOffset: new Cesium.Cartesian2(15, -10),
|
||||
}
|
||||
})
|
||||
this.viewer.entities.add(entity)
|
||||
|
||||
}
|
||||
|
||||
cal_point(positions1, positions2) {
|
||||
for (let i = 0; i < positions1.length; i++) {
|
||||
for (let j = 0; j < positions2.length; j++) {
|
||||
if (positions1[i].x === positions2[j].x &&
|
||||
positions1[i].y === positions2[j].y &&
|
||||
positions1[i].z === positions2[j].z
|
||||
) {
|
||||
return positions1[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cal_angle(id1, id2, type) {
|
||||
if (type === 1) {//水平&竖直
|
||||
return 90
|
||||
} else if (type === 2 || type === 3) {//水平&斜边 竖直&斜边
|
||||
let positions1 = this.id_map.get(id1).positions
|
||||
let positions2 = this.id_map.get(id2).positions
|
||||
let p1 = this.cartesian3Towgs84(positions1[0], this.viewer)
|
||||
let p2 = this.cartesian3Towgs84(positions1[1], this.viewer)
|
||||
let shuiping = this.computeDistance([p2, p1])
|
||||
let p3 = this.cartesian3Towgs84(positions2[0], this.viewer)
|
||||
let p4 = this.cartesian3Towgs84(positions2[1], this.viewer)
|
||||
let d = this.computeDistance([p3, p4])
|
||||
let h = Math.abs(p3.alt - p4.alt)
|
||||
let x = Math.sqrt(Math.pow(h, 2) + Math.pow(d, 2))
|
||||
if (shuiping == 0.00) {
|
||||
shuiping = Math.abs(p2.alt - p1.alt)
|
||||
}
|
||||
return (Math.acos(shuiping / x) * 180 / Math.PI).toFixed(2)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始测量
|
||||
*/
|
||||
start() {
|
||||
|
||||
if (!YJ.Measure.GetMeasureStatus()) {
|
||||
super.start()
|
||||
this.positions = []
|
||||
this.cachePositions = []
|
||||
let shuiping_line_id = this.randomString();//水平线
|
||||
let shuizhi_line_id = this.randomString();//竖直边
|
||||
let xiebian_line_id = this.randomString();//斜边
|
||||
|
||||
let angle1 = this.randomString();//角度1
|
||||
let angle2 = this.randomString();//角度2
|
||||
let angle3 = this.randomString();//角度3
|
||||
|
||||
|
||||
let xiebian_line_positions = [];//斜边
|
||||
|
||||
this.id_map = new Map()
|
||||
let first_point = {}
|
||||
this.id_map.set(xiebian_line_id, {positions: []})
|
||||
this.id_map.set(shuiping_line_id, {positions: []})
|
||||
this.id_map.set(shuizhi_line_id, {positions: []})
|
||||
|
||||
let leftEvent = (movement, car) => {
|
||||
xiebian_line_positions.push(car)
|
||||
|
||||
if (this.ids.length === 0) {//创建三角形
|
||||
first_point = this.cartesian3Towgs84(car, this.viewer)
|
||||
this.createPolyline(shuiping_line_id,)
|
||||
this.createPolyline(shuizhi_line_id,)
|
||||
this.createPolyline(xiebian_line_id,)
|
||||
|
||||
// this.cal_angle(shuiping_line_id, shuizhi_line_id, 1)
|
||||
// this.cal_angle(shuiping_line_id, xiebian_line_id, 2)
|
||||
// this.cal_angle(shuizhi_line_id, xiebian_line_id, 3)
|
||||
|
||||
// this.ids.push(shuiping_line_id)
|
||||
// this.ids.push(shuizhi_line_id)
|
||||
// this.ids.push(xiebian_line_id)
|
||||
}
|
||||
|
||||
this.ids.push(this.create_point(car))
|
||||
this.tip.setPosition(car, movement.position.x, movement.position.y)
|
||||
// // 隐藏斜边文字
|
||||
// let xiebian = this.id_map.get(xiebian_line_id)
|
||||
// let xbEntity = this.viewer.entities.getById(xiebian_line_id)
|
||||
// if(xbEntity) {
|
||||
// xbEntity.label.show = false
|
||||
// }
|
||||
if (xiebian_line_positions.length) {
|
||||
// xiebian.positions = xiebian_line_positions.concat(car)
|
||||
let p = this.cartesian3Towgs84(car, this.viewer)
|
||||
let shuzhi = this.id_map.get(shuizhi_line_id)
|
||||
let shuiping = this.id_map.get(shuiping_line_id)
|
||||
if (p.alt < first_point.alt) {
|
||||
shuzhi.positions[0] = car
|
||||
shuzhi.positions[1] = Cesium.Cartesian3.fromDegrees(p.lng, p.lat, first_point.alt)
|
||||
shuiping.positions[0] = Cesium.Cartesian3.fromDegrees(p.lng, p.lat, first_point.alt)
|
||||
shuiping.positions[1] = Cesium.Cartesian3.fromDegrees(first_point.lng, first_point.lat, first_point.alt)
|
||||
|
||||
} else {
|
||||
shuzhi.positions[0] = Cesium.Cartesian3.fromDegrees(first_point.lng, first_point.lat, p.alt)
|
||||
shuzhi.positions[1] = car
|
||||
|
||||
shuiping.positions[0] = Cesium.Cartesian3.fromDegrees(first_point.lng, first_point.lat, p.alt)
|
||||
shuiping.positions[1] = Cesium.Cartesian3.fromDegrees(first_point.lng, first_point.lat, first_point.alt)
|
||||
|
||||
}
|
||||
// shuizhi.positions = shuizhi_positions
|
||||
}
|
||||
if (xiebian_line_positions.length === 2) {
|
||||
this.end()
|
||||
}
|
||||
}
|
||||
this.event.mouse_left(leftEvent)
|
||||
this.event.mouse_move((movement, car) => {
|
||||
this.tip.setPosition(car, movement.endPosition.x, movement.endPosition.y)
|
||||
let xiebian = this.id_map.get(xiebian_line_id)
|
||||
|
||||
if (xiebian_line_positions.length) {
|
||||
xiebian.positions = xiebian_line_positions.concat(car)
|
||||
let p = this.cartesian3Towgs84(car, this.viewer)
|
||||
let shuzhi = this.id_map.get(shuizhi_line_id)
|
||||
let shuiping = this.id_map.get(shuiping_line_id)
|
||||
if (p.alt < first_point.alt) {
|
||||
shuzhi.positions[0] = car
|
||||
shuzhi.positions[1] = Cesium.Cartesian3.fromDegrees(p.lng, p.lat, first_point.alt)
|
||||
shuiping.positions[0] = Cesium.Cartesian3.fromDegrees(p.lng, p.lat, first_point.alt)
|
||||
shuiping.positions[1] = Cesium.Cartesian3.fromDegrees(first_point.lng, first_point.lat, first_point.alt)
|
||||
|
||||
} else {
|
||||
shuzhi.positions[0] = Cesium.Cartesian3.fromDegrees(first_point.lng, first_point.lat, p.alt)
|
||||
shuzhi.positions[1] = car
|
||||
|
||||
shuiping.positions[0] = Cesium.Cartesian3.fromDegrees(first_point.lng, first_point.lat, p.alt)
|
||||
shuiping.positions[1] = Cesium.Cartesian3.fromDegrees(first_point.lng, first_point.lat, first_point.alt)
|
||||
|
||||
}
|
||||
// shuizhi.positions = shuizhi_positions
|
||||
}
|
||||
})
|
||||
this.event.mouse_right((movement, car) => {
|
||||
this.end()
|
||||
})
|
||||
this.event.gesture_pinck_start((movement, cartesian) => {
|
||||
let startTime = new Date()
|
||||
let pos = {
|
||||
position: {
|
||||
x: (movement.position1.x + movement.position2.x) / 2,
|
||||
y: (movement.position1.y + movement.position2.y) / 2
|
||||
}
|
||||
}
|
||||
this.event.gesture_pinck_end(() => {
|
||||
let endTime = new Date()
|
||||
if (endTime - startTime >= 500) {
|
||||
// 长按取消
|
||||
this.end()
|
||||
}
|
||||
else {
|
||||
leftEvent(pos, cartesian)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 结束测量
|
||||
*/
|
||||
end() {
|
||||
super.end();
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除测量
|
||||
*/
|
||||
destroy() {
|
||||
super.destroy()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default MeasureTriangle
|
||||
197
src/Measure/MeasureTyArea/index.js
Normal file
197
src/Measure/MeasureTyArea/index.js
Normal file
@ -0,0 +1,197 @@
|
||||
/**
|
||||
* @name: index
|
||||
* @author: Administrator
|
||||
* @date: 2022-07-11 17:28
|
||||
* @description:index
|
||||
* @update: 2022-07-11 17:28
|
||||
*/
|
||||
import Measure from "../index"
|
||||
|
||||
/**@extends Measure*/
|
||||
class MeasureTyArea extends Measure {
|
||||
/**
|
||||
* @constructor
|
||||
* @param sdk
|
||||
* @description 投影面积测量
|
||||
* */
|
||||
constructor(sdk, options = {}) {
|
||||
super(sdk, options);
|
||||
this.options.lineColor = '#ffdf53'
|
||||
this.polygon_id = ""
|
||||
}
|
||||
|
||||
static create_polygon(that) {
|
||||
let id = that.randomString()
|
||||
|
||||
let scaleByDistance = new Cesium.NearFarScalar(2000, 1, 100000, 0)
|
||||
|
||||
let e = that.viewer.entities.add(
|
||||
new Cesium.Entity({
|
||||
id: id,
|
||||
label: {
|
||||
text: new Cesium.CallbackProperty(() => {
|
||||
return that.text
|
||||
}, false),
|
||||
//标注文字描述
|
||||
font: '20px Microsoft YaHei',
|
||||
fillColor: Cesium.Color.fromCssColorString('#ffffff'),
|
||||
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
|
||||
//标注的遮挡距离设置为100则视角与标注的距离大于100米时会有遮挡
|
||||
// distanceDisplayCondition: this.distanceDisplayCondition,
|
||||
|
||||
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
||||
|
||||
// scaleByDistance,
|
||||
scale: 1,
|
||||
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
||||
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
},
|
||||
position: new Cesium.CallbackProperty(() => {
|
||||
return that.center
|
||||
}, false),
|
||||
polygon: {
|
||||
classificationType: Cesium.ClassificationType.BOTH,
|
||||
hierarchy: new Cesium.CallbackProperty((e) => {
|
||||
return new Cesium.PolygonHierarchy(that.positions)
|
||||
}, false),
|
||||
material: new Cesium.Color.fromCssColorString(that.options.color || that.defaultColor),
|
||||
zIndex: 99999999
|
||||
},
|
||||
polyline: {
|
||||
positions: new Cesium.CallbackProperty(() => {
|
||||
if (that.positions.length)
|
||||
return that.positions.concat(that.positions[0])
|
||||
return that.positions
|
||||
}, false),
|
||||
width: 2,
|
||||
material: new Cesium.PolylineDashMaterialProperty({
|
||||
color: new Cesium.Color.fromCssColorString(that.options.lineColor || that.defaultColor),
|
||||
dashLength: 20, //短划线长度
|
||||
}),
|
||||
clampToGround: true,
|
||||
zIndex: 99999999
|
||||
}
|
||||
})
|
||||
)
|
||||
return id
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始测量
|
||||
*/
|
||||
start() {
|
||||
if (!YJ.Measure.GetMeasureStatus()) {
|
||||
super.start()
|
||||
this.ids = []
|
||||
this.positions = []
|
||||
this.text = ""
|
||||
this.center = new Cesium.Cartesian3()
|
||||
this.cachePositions = []
|
||||
let height = 0
|
||||
let lastArea = 0
|
||||
let lastcneter
|
||||
|
||||
let leftEvent = (movement, car) => {
|
||||
if (this.ids.length === 0) {
|
||||
this.polygon_id = MeasureTyArea.create_polygon(this)
|
||||
}
|
||||
this.cachePositions.push({ ...car })
|
||||
this.ids.push(this.create_point({ ...car }, false))
|
||||
let po = this.cartesian3Towgs84({ ...car }, this.viewer)
|
||||
if (po.alt > height) {
|
||||
height = po.alt
|
||||
}
|
||||
|
||||
this.positions = this.cachePositions.concat({ ...car })
|
||||
this.tip.setPosition({ ...car }, movement.position.x, movement.position.y)
|
||||
if (this.positions.length > 2) {
|
||||
let arr = []
|
||||
this.positions.forEach(item => {
|
||||
let p = this.cartesian3Towgs84(item, this.viewer)
|
||||
arr.push({ lng: p.lng, lat: p.lat })
|
||||
})
|
||||
let center = this.computeCenter(arr)
|
||||
let area = this.computeArea(arr)
|
||||
lastArea = area
|
||||
this.center = new Cesium.Cartesian3.fromDegrees(center.lng, center.lat, height)
|
||||
lastcneter = this.center
|
||||
this.text = "投影面积:" + area + " ㎡"
|
||||
}
|
||||
}
|
||||
this.event.mouse_left(leftEvent)
|
||||
this.event.mouse_move((movement, car) => {
|
||||
this.tip.setPosition({ ...car }, movement.endPosition.x, movement.endPosition.y)
|
||||
this.positions = this.cachePositions.concat({ ...car })
|
||||
if (this.positions.length > 2) {
|
||||
let arr = []
|
||||
this.positions.forEach(item => {
|
||||
let p = this.cartesian3Towgs84(item, this.viewer)
|
||||
arr.push({ lng: p.lng, lat: p.lat })
|
||||
})
|
||||
let center = this.computeCenter(arr)
|
||||
let area = this.computeArea(arr)
|
||||
this.center = new Cesium.Cartesian3.fromDegrees(center.lng, center.lat, height)
|
||||
this.text = "投影面积:" + area + " ㎡"
|
||||
}
|
||||
})
|
||||
this.event.mouse_right((movement, car) => {
|
||||
this.positions = this.cachePositions
|
||||
this.center = lastcneter
|
||||
if (this.positions.length < 3) {
|
||||
this.text = ""
|
||||
let error = '面积计算至少需要三个坐标!'
|
||||
console.warn(error)
|
||||
window.ELEMENT && window.ELEMENT.Message({
|
||||
message: error,
|
||||
type: 'warning',
|
||||
duration: 1500
|
||||
});
|
||||
this.destroy()
|
||||
}
|
||||
else {
|
||||
this.text = "投影面积:" + lastArea + " ㎡"
|
||||
}
|
||||
this.end()
|
||||
})
|
||||
this.event.gesture_pinck_start((movement, cartesian) => {
|
||||
let startTime = new Date()
|
||||
let pos = {
|
||||
position: {
|
||||
x: (movement.position1.x + movement.position2.x) / 2,
|
||||
y: (movement.position1.y + movement.position2.y) / 2
|
||||
}
|
||||
}
|
||||
this.event.gesture_pinck_end(() => {
|
||||
let endTime = new Date()
|
||||
if (endTime - startTime >= 500) {
|
||||
// 长按取消
|
||||
this.positions = this.cachePositions
|
||||
this.end()
|
||||
}
|
||||
else {
|
||||
leftEvent(pos, cartesian)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除测量
|
||||
*/
|
||||
destroy() {
|
||||
[this.polygon_id, ...this.ids].forEach(id => {
|
||||
this.remove_entity(id)
|
||||
})
|
||||
super.destroy()
|
||||
}
|
||||
|
||||
/**
|
||||
* 结束测量
|
||||
*/
|
||||
end() {
|
||||
super.end()
|
||||
}
|
||||
}
|
||||
|
||||
export default MeasureTyArea
|
||||
16
src/Measure/clear.js
Normal file
16
src/Measure/clear.js
Normal file
@ -0,0 +1,16 @@
|
||||
/**
|
||||
* @name: clear
|
||||
* @author: Administrator
|
||||
* @date: 2022-07-11 15:28
|
||||
* @description:clear
|
||||
* @update: 2022-07-11 15:28
|
||||
*/
|
||||
|
||||
function Clear() {
|
||||
YJ.Measure.Measures.forEach(m => {
|
||||
m.destroy()
|
||||
})
|
||||
YJ.Measure.Measures = []
|
||||
}
|
||||
|
||||
export {Clear}
|
||||
80
src/Measure/index.js
Normal file
80
src/Measure/index.js
Normal file
@ -0,0 +1,80 @@
|
||||
import MouseEvent from "../Event";
|
||||
import MouseTip from "../MouseTip";
|
||||
import Tools from "../Tools";
|
||||
|
||||
/**
|
||||
* @name: measure
|
||||
* @author: Administrator
|
||||
* @date: 2022-07-11 10:52
|
||||
* @description:measure
|
||||
* @update: 2022-07-11 10:52
|
||||
*/
|
||||
|
||||
class Measure extends Tools {
|
||||
constructor(sdk, options = {text: "左键开始,右键结束;"}) {
|
||||
super(sdk, options)
|
||||
this.options = {...options}
|
||||
this.event = new MouseEvent(sdk)
|
||||
this.tip = new MouseTip(options.text, sdk)
|
||||
this.viewer = sdk.viewer
|
||||
this.defaultColor = 'rgba(246,49,49,0.55)'
|
||||
this.ids = []
|
||||
YJ.Measure.Measures.push(this)
|
||||
this._isDestroy = false
|
||||
// this.pickStatus = {pick: YJ.getEarth().interaction.picking.enabled}
|
||||
}
|
||||
|
||||
start() {
|
||||
this.setPickStatus(false)
|
||||
YJ.Measure.SetMeasureStatus(true)
|
||||
}
|
||||
|
||||
destroy() {
|
||||
// YJ.Measure.Measures.pop()
|
||||
this._isDestroy = true
|
||||
this.end()
|
||||
this.ids.forEach(id => {
|
||||
this.remove_entity(id)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
end() {
|
||||
// this.ids.forEach(id => {
|
||||
// this.remove_entity(id)
|
||||
// })
|
||||
//还原上一次的状态
|
||||
// this.setPickStatus(this.pickStatus.pick)
|
||||
YJ.Measure.SetMeasureStatus(false)
|
||||
this.tip && this.tip.destroy()
|
||||
this.event && this.event.destroy()
|
||||
this.tip = null
|
||||
this.event = null
|
||||
}
|
||||
|
||||
create_point(cartesian,show = true) {
|
||||
let id = this.randomString()
|
||||
let p = this.cartesian3Towgs84(cartesian, this.viewer)
|
||||
this.viewer.entities.add(
|
||||
new Cesium.Entity({
|
||||
id: id,
|
||||
position: Cesium.Cartesian3.fromDegrees(p.lng, p.lat, p.alt),
|
||||
billboard: {
|
||||
show: show,
|
||||
image: this.getSourceRootPath() + '/img/point.png',
|
||||
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
||||
color: Cesium.Color.WHITE.withAlpha(0.99)
|
||||
}
|
||||
})
|
||||
)
|
||||
return id
|
||||
}
|
||||
|
||||
remove_entity(id) {
|
||||
this.viewer.entities.removeById(id)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default Measure
|
||||
123
src/MouseTip/index.js
Normal file
123
src/MouseTip/index.js
Normal file
@ -0,0 +1,123 @@
|
||||
/**
|
||||
* @name: index
|
||||
* @author: Administrator
|
||||
* @date: 2022-06-14 14:37
|
||||
* @description:index
|
||||
* @update: 2022-06-14 14:37
|
||||
*/
|
||||
import Tools from "../Tools";
|
||||
|
||||
//鼠标tip
|
||||
export default class MouseTip {
|
||||
constructor(text = '左键开始,右键结束', sdk) {
|
||||
this.point = undefined
|
||||
this.text = text
|
||||
this.div = undefined
|
||||
this.mouse_type = 0
|
||||
this.position = new Cesium.Cartesian3()
|
||||
|
||||
this.viewer = sdk.viewer
|
||||
this.create_tip(this.viewer)
|
||||
}
|
||||
|
||||
set_text(text) {
|
||||
let textElm = this.div.getElementsByTagName('p')[0]
|
||||
textElm.innerText = text
|
||||
}
|
||||
|
||||
get_mouse_style(type) {
|
||||
let url = 'lib/img/'
|
||||
let style = '' //默认的鼠标箭头样式
|
||||
switch (type) {
|
||||
case 1:
|
||||
style = 'move.png' //移动样式
|
||||
break
|
||||
|
||||
default:
|
||||
style = 'arrow.png'
|
||||
break
|
||||
}
|
||||
return 'url(' + url + style + '),auto'
|
||||
}
|
||||
|
||||
create_tip(viewer) {
|
||||
// let tool = new Tools()
|
||||
// this.point = viewer.entities.add(
|
||||
// new Cesium.Entity({
|
||||
// position: new Cesium.CallbackProperty(() => {
|
||||
// return this.position
|
||||
// }, false),
|
||||
// billboard: {
|
||||
// image: tool.getSourceRootPath() + '/img/point.png',
|
||||
// verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
// disableDepthTestDistance: 100000000
|
||||
// }
|
||||
// })
|
||||
// )
|
||||
// tool = null
|
||||
// this.style_tip(viewer, this.mouse_type)
|
||||
this.create_tooltip()
|
||||
}
|
||||
|
||||
setPosition(position, x, y) {
|
||||
this.position = position
|
||||
this.move_tooltip(x, y)
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.viewer.entities.remove(this.point)
|
||||
this.remove_tooltip()
|
||||
// this.style_tip(viewer)
|
||||
}
|
||||
|
||||
create_tooltip() {
|
||||
let tool = new Tools()
|
||||
this.div = document.createElement('div')
|
||||
let c = "#ec131a"
|
||||
this.div.setAttribute(
|
||||
'style',
|
||||
'position: absolute;z-index: 777;color: ' + c + ';left:10px;top:0px;pointer-events: none;'
|
||||
)
|
||||
let textElm = document.createElement('p')
|
||||
textElm.style.margin = '0px'
|
||||
textElm.style.padding = '0px'
|
||||
textElm.innerText = this.text
|
||||
this.div.appendChild(textElm)
|
||||
let imgElm = document.createElement('div')
|
||||
imgElm.style.width = '12px'
|
||||
imgElm.style.height = '12px'
|
||||
imgElm.style.background = `url(${tool.getSourceRootPath() + '/img/point.png'}) 100% 100% no-repeat`
|
||||
imgElm.style.backgroundSize = '100% 100%'
|
||||
imgElm.style.position = 'absolute'
|
||||
imgElm.style.left = '-36px'
|
||||
imgElm.style.top = '-4px'
|
||||
this.div.style.display = 'none'
|
||||
this.div.appendChild(imgElm)
|
||||
tool = null
|
||||
document.querySelector('body').appendChild(this.div)
|
||||
}
|
||||
|
||||
/*移动时的鼠标样式*/
|
||||
style_tip(viewer, type = 0) {
|
||||
viewer._element.style.cursor = this.get_mouse_style(type)
|
||||
}
|
||||
|
||||
remove_tooltip() {
|
||||
document.querySelector('body').contains(this.div) && document.querySelector('body').removeChild(this.div)
|
||||
}
|
||||
|
||||
move_tooltip(x, y) {
|
||||
let top = 0
|
||||
let left = 0
|
||||
this.div.style.display = 'block'
|
||||
|
||||
if (this.viewer && this.viewer._element) {
|
||||
let element = this.viewer._element.getElementsByClassName('cesium-widget')[0].getElementsByTagName('canvas')[0]
|
||||
top = element.getBoundingClientRect().top + window.scrollY
|
||||
left = element.getBoundingClientRect().left + window.scrollX
|
||||
}
|
||||
|
||||
this.div.style.left = x + 30 + left + 'px'
|
||||
this.div.style.top = y + top + 'px'
|
||||
}
|
||||
}
|
||||
89
src/Obj/AirLine/DrawTakeOff.js
Normal file
89
src/Obj/AirLine/DrawTakeOff.js
Normal file
@ -0,0 +1,89 @@
|
||||
import MouseTip from '../../MouseTip/index'
|
||||
import MouseEvent from '../../Event/index'
|
||||
import Draw from '../../Draw/draw'
|
||||
|
||||
class DrawTakeOff extends Draw {
|
||||
/**
|
||||
* @constructor
|
||||
* @desc 获取坐标点
|
||||
* */
|
||||
constructor(sdk, options = {}) {
|
||||
super(sdk, options)
|
||||
this.options.tipText = options.tipText
|
||||
? options.tipText
|
||||
: '左键确定,右键结束;'
|
||||
}
|
||||
|
||||
/**
|
||||
* @desc 开始动态获取坐标点
|
||||
* @method start
|
||||
* @param cb {function} 回调函数
|
||||
* @memberOf DrawPoint
|
||||
* @example draw.start((err,position)=>{
|
||||
*
|
||||
* })
|
||||
* */
|
||||
|
||||
start(cb) {
|
||||
// eslint-disable-next-line no-undef
|
||||
if (YJ.Measure.GetMeasureStatus()) {
|
||||
cb('上一次测量未结束')
|
||||
} else {
|
||||
let car = undefined
|
||||
// eslint-disable-next-line no-undef
|
||||
YJ.Measure.SetMeasureStatus(true)
|
||||
// this.options
|
||||
this.tip = new MouseTip(this.options.tipText, this.sdk)
|
||||
this.event = new MouseEvent(this.sdk)
|
||||
this.isEntity = false
|
||||
this.event.mouse_left((movement, cartesian) => {
|
||||
this.end()
|
||||
let p = this.cartesian3Towgs84(car || cartesian, this.viewer)
|
||||
var pickedObject = this.viewer.scene.pick(movement.position)
|
||||
if (
|
||||
Cesium.defined(pickedObject) &&
|
||||
Cesium.defined(pickedObject.id) &&
|
||||
pickedObject.id.id === window.airportEntity.options.id
|
||||
) {
|
||||
this.isEntity = true
|
||||
}
|
||||
cb(null, p, this.isEntity)
|
||||
})
|
||||
this.event.mouse_right((movement, cartesian) => {
|
||||
this.end()
|
||||
cb(false)
|
||||
})
|
||||
this.event.mouse_move((movement, cartesian) => {
|
||||
car = cartesian
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
movement.endPosition.x,
|
||||
movement.endPosition.y
|
||||
)
|
||||
})
|
||||
|
||||
this.event.gesture_pinck_start((movement, cartesian) => {
|
||||
let startTime = new Date()
|
||||
this.event.gesture_pinck_end(() => {
|
||||
let endTime = new Date()
|
||||
if (endTime - startTime >= 500) {
|
||||
this.end()
|
||||
cb(false)
|
||||
} else {
|
||||
this.end()
|
||||
let p = this.cartesian3Towgs84(car || cartesian, this.viewer)
|
||||
cb(null, p)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
end() {
|
||||
YJ.Measure.SetMeasureStatus(false)
|
||||
this.event.destroy()
|
||||
this.tip.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
export default DrawTakeOff
|
||||
112
src/Obj/AirLine/GenerateRoute.js
Normal file
112
src/Obj/AirLine/GenerateRoute.js
Normal file
@ -0,0 +1,112 @@
|
||||
// 根据米生成航线
|
||||
function flyLine(earth, positions, unit) {
|
||||
let arr = []
|
||||
positions.forEach(item => {
|
||||
arr.push([item.lng, item.lat])
|
||||
})
|
||||
arr.push(arr[0])
|
||||
// eslint-disable-next-line no-undef
|
||||
const turfPolygon = turf.polygon([arr])
|
||||
// 获取四至
|
||||
// eslint-disable-next-line no-undef
|
||||
const turfExtent = turf.bbox(turfPolygon)
|
||||
// 在turfPolygon中按网格取样点,网格间距3米
|
||||
// eslint-disable-next-line no-undef
|
||||
const turfSamplePoints = turf.pointGrid(turfExtent, unit / 1000, {
|
||||
units: 'kilometers',
|
||||
mask: turfPolygon
|
||||
})
|
||||
// 将turf取样点转为Cesium的取样点
|
||||
const cesiumSamplePoints = []
|
||||
for (let i = 0; i < turfSamplePoints.features.length; i++) {
|
||||
const coord = turfSamplePoints.features[i].geometry.coordinates
|
||||
cesiumSamplePoints.push([coord[0], coord[1]])
|
||||
}
|
||||
// 计算两点的距离
|
||||
function fromTo(point1, point2) {
|
||||
if (!point2) {
|
||||
return
|
||||
}
|
||||
// eslint-disable-next-line no-undef
|
||||
let from = turf.point(point1)
|
||||
// eslint-disable-next-line no-undef
|
||||
let to = turf.point(point2)
|
||||
// eslint-disable-next-line no-undef
|
||||
return Math.round(turf.distance(from, to) * 1000)
|
||||
}
|
||||
// 进行分组并进行奇数反转
|
||||
let polylinePosition = []
|
||||
let flag = 0
|
||||
let index = -1
|
||||
for (let i = 0; i < cesiumSamplePoints.length; i++) {
|
||||
if (fromTo(cesiumSamplePoints[i], cesiumSamplePoints[i + 1]) > unit) {
|
||||
index++
|
||||
let arr = cesiumSamplePoints.slice(flag, i + 1)
|
||||
if (index % 2 !== 0) {
|
||||
arr.reverse()
|
||||
}
|
||||
polylinePosition.push(arr)
|
||||
flag = i + 1
|
||||
}
|
||||
}
|
||||
let arr2 = cesiumSamplePoints.slice(flag, cesiumSamplePoints.length)
|
||||
if ((index + 1) % 2 !== 0) {
|
||||
arr2.reverse()
|
||||
}
|
||||
polylinePosition.push(arr2)
|
||||
return polylinePosition.flat()
|
||||
}
|
||||
// 获取高程
|
||||
function sampleHeightMostDetailed(earth, positions) {
|
||||
return earth.viewer.scene.sampleHeightMostDetailed([
|
||||
new Cesium.Cartographic.fromDegrees(positions[0], positions[1])
|
||||
])
|
||||
}
|
||||
// 计算高程
|
||||
async function countHeight(earth, item) {
|
||||
return await sampleHeightMostDetailed(earth, item)
|
||||
}
|
||||
function cartesian3Towgs84(earth, cartesian) {
|
||||
const viewer = earth.viewer
|
||||
var ellipsoid = viewer.scene.globe.ellipsoid
|
||||
var cartesian3 = new Cesium.Cartesian3(cartesian.x, cartesian.y, cartesian.z)
|
||||
var cartographic = ellipsoid.cartesianToCartographic(cartesian3)
|
||||
var lat = Cesium.Math.toDegrees(cartographic.latitude)
|
||||
var lng = Cesium.Math.toDegrees(cartographic.longitude)
|
||||
var alt = cartographic.height < 0 ? 0 : cartographic.height
|
||||
return {
|
||||
longitude: lng,
|
||||
latitude: lat,
|
||||
height: alt
|
||||
}
|
||||
}
|
||||
//更新路径高度
|
||||
async function updateHeight(earth, height, positions, cb) {
|
||||
let Cartesian = []
|
||||
let locationList = []
|
||||
for (let i = 0; i < positions.length; i++) {
|
||||
const element = positions[i]
|
||||
let Cartographic = await countHeight(earth, element)
|
||||
if (isNaN(Cartographic[0].height)) {
|
||||
Cartographic[0].height = 0
|
||||
}
|
||||
Cartographic[0].height = Cartographic[0].height + height
|
||||
Cartesian.push(Cesium.Cartographic.toCartesian(Cartographic[0]))
|
||||
if (i < positions.length) {
|
||||
cb({
|
||||
cur: i + 1,
|
||||
total: positions.length
|
||||
})
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < Cartesian.length; i++) {
|
||||
locationList.push(cartesian3Towgs84(earth, Cartesian[i]))
|
||||
}
|
||||
let arr = [locationList, Cartesian]
|
||||
cb(arr)
|
||||
}
|
||||
let GenerateRoute = {
|
||||
flyLine,
|
||||
updateHeight
|
||||
}
|
||||
export default GenerateRoute
|
||||
272
src/Obj/AirLine/billord_point_line.js
Normal file
272
src/Obj/AirLine/billord_point_line.js
Normal file
@ -0,0 +1,272 @@
|
||||
export default class BillordPointLine {
|
||||
constructor(options, viewer) {
|
||||
this.options = { ...options }
|
||||
this.pointEntity = null
|
||||
this.billboardEntity = null
|
||||
this.lineEntity = null
|
||||
this.updatedPosition = []
|
||||
this.pointUpdatedPosition = []
|
||||
this.viewer = viewer
|
||||
this.handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
|
||||
this.pinBuilder = new Cesium.PinBuilder()
|
||||
this.index = null
|
||||
//定义屏幕点击事件处理器
|
||||
BillordPointLine.setDefaultValue(this)
|
||||
BillordPointLine.init(this)
|
||||
}
|
||||
static setDefaultValue(that) {
|
||||
that.options.positions = that.options.positions || {}
|
||||
that.options.normalHeight = that.options.normalHeight || 100
|
||||
that.options.airHeight = that.options.airHeight || 100
|
||||
that.options.image = that.options.image || '/static/img/cluster2.png'
|
||||
that.options.show = that.options.show || true
|
||||
that.options.index = that.options.index || 1
|
||||
that.options.saveFun = that.options.saveFun || null
|
||||
that.options.selectFun = that.options.selectFun || null
|
||||
that.options.keyboard = that.options.keyboard ?? true
|
||||
that.options.updateFrustumFun = that.options.updateFrustumFun || null
|
||||
that.options.frustum = that.options.frustum || null
|
||||
}
|
||||
static init(that) {
|
||||
let positions = that.options.positions
|
||||
// 添加一个Point,稍微偏离地面高度,使其完全可见
|
||||
that.pointEntity = that.viewer.entities.add({
|
||||
show: that.options.show,
|
||||
position: Cesium.Cartesian3.fromDegrees(positions.lng, positions.lat, 0), // 地面上
|
||||
point: {
|
||||
pixelSize: 8,
|
||||
color: Cesium.Color.WITHE,
|
||||
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, // 使用相对地面或贴地,
|
||||
disableDepthTestDistance: 0
|
||||
}
|
||||
})
|
||||
//
|
||||
let pinIndex = that.pinBuilder
|
||||
.fromText(
|
||||
that.options.index,
|
||||
Cesium.Color.fromCssColorString('#00d590'),
|
||||
36
|
||||
)
|
||||
.toDataURL()
|
||||
let altitude = 0
|
||||
if (positions.altitude) {
|
||||
altitude = positions.altitude
|
||||
} else {
|
||||
altitude = that.options.normalHeight
|
||||
}
|
||||
// 添加一个Billboard
|
||||
that.billboardEntity = that.viewer.entities.add({
|
||||
show: that.options.show,
|
||||
position: Cesium.Cartesian3.fromDegrees(
|
||||
positions.lng,
|
||||
positions.lat,
|
||||
positions.alt + that.options.normalHeight
|
||||
),
|
||||
// 判断altitude是否有值
|
||||
|
||||
label: {
|
||||
text: `Lat: ${positions.lng.toFixed(8)}\nLon: ${positions.lat.toFixed(
|
||||
8
|
||||
)}\nAlt: ${altitude.toFixed(8)}m`,
|
||||
font: '14px sans-serif',
|
||||
fillColor: Cesium.Color.YELLOW,
|
||||
outlineColor: Cesium.Color.BLACK,
|
||||
outlineWidth: 2,
|
||||
pixelOffset: new Cesium.Cartesian2(0, -60), // 标签偏移量,防止重叠
|
||||
heightReference: Cesium.HeightReference.RELATIVE_TO_TERRAIN, // 确保标签与地面贴合
|
||||
show: false
|
||||
},
|
||||
billboard: {
|
||||
image: pinIndex, // 示例图像路径
|
||||
verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 图像底部对齐
|
||||
width: 36,
|
||||
height: 36
|
||||
},
|
||||
index: that.options.index
|
||||
})
|
||||
|
||||
// 创建一个连接Point和Billboard的竖线
|
||||
that.lineEntity = that.viewer.entities.add({
|
||||
show: that.options.show,
|
||||
polyline: {
|
||||
positions: new Cesium.CallbackProperty(() => {
|
||||
return [
|
||||
that.pointEntity.position.getValue(),
|
||||
that.billboardEntity.position.getValue()
|
||||
]
|
||||
}, false),
|
||||
width: 1,
|
||||
material: new Cesium.PolylineOutlineMaterialProperty({
|
||||
outlineColor: Cesium.Color.GAINSBORO,
|
||||
outlineWidth: 1,
|
||||
color: Cesium.Color.WITHE
|
||||
}),
|
||||
zIndex: 99999999
|
||||
}
|
||||
})
|
||||
if (that.options.keyboard) {
|
||||
that.changeAltitude()
|
||||
}
|
||||
that.handler.setInputAction(function(movement) {
|
||||
var pickedObject = that.viewer.scene.pick(movement.position)
|
||||
if (
|
||||
Cesium.defined(pickedObject) &&
|
||||
Cesium.defined(pickedObject.id) &&
|
||||
pickedObject.id === that.billboardEntity
|
||||
) {
|
||||
if (that.options.selectFun) {
|
||||
that.options.selectFun(that.billboardEntity.index - 1)
|
||||
}
|
||||
}
|
||||
}, Cesium.ScreenSpaceEventType.LEFT_CLICK)
|
||||
}
|
||||
// 改变高度
|
||||
changeAltitude() {
|
||||
var isMouseDown = false
|
||||
var startPosition
|
||||
var initialHeight
|
||||
let that = this
|
||||
let HHH = false
|
||||
// 标识Alt键是否被按下
|
||||
document.addEventListener('keydown', function(event) {
|
||||
const key = event.key // 获取按下的键名
|
||||
// 检查特定键是否被按下
|
||||
if (key === 'h') {
|
||||
HHH = true
|
||||
}
|
||||
})
|
||||
document.addEventListener('keyup', function(event) {
|
||||
HHH = false
|
||||
})
|
||||
// 按下鼠标左键
|
||||
this.handler.setInputAction(function(movement) {
|
||||
var pickedObject = that.viewer.scene.pick(movement.position)
|
||||
if (
|
||||
Cesium.defined(pickedObject) &&
|
||||
Cesium.defined(pickedObject.id) &&
|
||||
pickedObject.id === that.billboardEntity
|
||||
) {
|
||||
isMouseDown = true
|
||||
startPosition = movement.position
|
||||
|
||||
// 获取Billboard当前的地理高度
|
||||
var positionCartographic = Cesium.Cartographic.fromCartesian(
|
||||
that.billboardEntity.position.getValue()
|
||||
)
|
||||
initialHeight = positionCartographic.height
|
||||
}
|
||||
}, Cesium.ScreenSpaceEventType.LEFT_DOWN)
|
||||
// 移动鼠标
|
||||
this.handler.setInputAction(function(movement) {
|
||||
if (isMouseDown && HHH == false) {
|
||||
// 移动位置
|
||||
var newCartesian = that.viewer.scene.pickPosition(movement.endPosition)
|
||||
that.disableCameraDrag(that.viewer, false)
|
||||
if (newCartesian) {
|
||||
var newCartographic = Cesium.Cartographic.fromCartesian(newCartesian)
|
||||
// 保持高度不变
|
||||
var newLongitude = newCartographic.longitude
|
||||
var newLatitude = newCartographic.latitude
|
||||
var updatedPosition = Cesium.Cartesian3.fromRadians(
|
||||
newLongitude,
|
||||
newLatitude,
|
||||
initialHeight
|
||||
)
|
||||
var pointUpdatedPosition = Cesium.Cartesian3.fromRadians(
|
||||
newLongitude,
|
||||
newLatitude,
|
||||
0
|
||||
)
|
||||
that.billboardEntity.position = new Cesium.CallbackProperty(() => {
|
||||
return updatedPosition
|
||||
}, false)
|
||||
that.billboardEntity.label.text = `Lat: ${Cesium.Math.toDegrees(
|
||||
newLongitude
|
||||
).toFixed(6)}\nLon: ${Cesium.Math.toDegrees(newLatitude).toFixed(
|
||||
6
|
||||
)}\nAlt: ${initialHeight.toFixed(2)}m`
|
||||
that.pointEntity.position = new Cesium.CallbackProperty(() => {
|
||||
return pointUpdatedPosition
|
||||
}, false)
|
||||
}
|
||||
}
|
||||
if (isMouseDown && HHH) {
|
||||
console.log(HHH)
|
||||
// 改变高度
|
||||
var endPosition = movement.endPosition
|
||||
var deltaY = startPosition.y - endPosition.y // 计算Y轴方向上的移动距离
|
||||
// 根据鼠标移动的距离来调整高度
|
||||
var newHeight = initialHeight + deltaY
|
||||
// 更新billboard位置
|
||||
var positionCartographic = Cesium.Cartographic.fromCartesian(
|
||||
that.billboardEntity.position.getValue()
|
||||
)
|
||||
var newPosition = Cesium.Cartesian3.fromDegrees(
|
||||
Cesium.Math.toDegrees(positionCartographic.longitude),
|
||||
Cesium.Math.toDegrees(positionCartographic.latitude),
|
||||
newHeight
|
||||
)
|
||||
// 禁用相机
|
||||
that.disableCameraDrag(that.viewer, false)
|
||||
that.billboardEntity.position = new Cesium.CallbackProperty(() => {
|
||||
return newPosition
|
||||
}, false)
|
||||
that.billboardEntity.label.text = `Lat: ${Cesium.Math.toDegrees(
|
||||
positionCartographic.longitude
|
||||
).toFixed(6)}\nLon: ${Cesium.Math.toDegrees(
|
||||
positionCartographic.latitude
|
||||
).toFixed(6)}\nAlt: ${newHeight.toFixed(2)}m`
|
||||
}
|
||||
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
|
||||
// 松开鼠标左键
|
||||
this.handler.setInputAction(function(movement) {
|
||||
var pickedObject = that.viewer.scene.pick(movement.position)
|
||||
isMouseDown = false // 禁用相机
|
||||
HHH = false //
|
||||
that.disableCameraDrag(that.viewer, true)
|
||||
// 更新frustum的位置
|
||||
if (
|
||||
Cesium.defined(pickedObject) &&
|
||||
Cesium.defined(pickedObject.id) &&
|
||||
pickedObject.id === that.billboardEntity
|
||||
) {
|
||||
if (that.options.saveFun) {
|
||||
that.options.saveFun(null, false)
|
||||
}
|
||||
if (that.options.selectFun) {
|
||||
that.options.selectFun(that.billboardEntity.index - 1)
|
||||
}
|
||||
that.options.frustum.updatePositionHeight(
|
||||
that.billboardEntity.position.getValue()
|
||||
)
|
||||
}
|
||||
}, Cesium.ScreenSpaceEventType.LEFT_UP)
|
||||
}
|
||||
|
||||
disableCameraDrag(viewer, bool) {
|
||||
viewer.scene.screenSpaceCameraController.enableRotate = bool
|
||||
viewer.scene.screenSpaceCameraController.enableTranslate = bool
|
||||
viewer.scene.screenSpaceCameraController.enableZoom = bool
|
||||
viewer.scene.screenSpaceCameraController.enableTilt = bool
|
||||
viewer.scene.screenSpaceCameraController.enableLook = bool
|
||||
}
|
||||
get show() {
|
||||
return this.options.show
|
||||
}
|
||||
/**
|
||||
* @param {boolean} bool
|
||||
*/
|
||||
set show(bool) {
|
||||
if (typeof bool === 'boolean') {
|
||||
this.pointEntity.show = bool
|
||||
this.billboardEntity.show = bool
|
||||
this.lineEntity.show = bool
|
||||
}
|
||||
}
|
||||
|
||||
remove() {
|
||||
this.viewer.entities.remove(this.pointEntity)
|
||||
this.viewer.entities.remove(this.billboardEntity)
|
||||
this.viewer.entities.remove(this.lineEntity)
|
||||
}
|
||||
}
|
||||
673
src/Obj/AirLine/frustum.js
Normal file
673
src/Obj/AirLine/frustum.js
Normal file
@ -0,0 +1,673 @@
|
||||
export default class Frustum {
|
||||
constructor(options, viewer, viewer1) {
|
||||
this.options = { ...options }
|
||||
this.viewer = viewer
|
||||
this.viewer1 = viewer1
|
||||
this.head = 0
|
||||
this.pitch = 90
|
||||
this.po = 0.00001
|
||||
this.position = null
|
||||
this.hpr = null
|
||||
this.currentFrustumOutline = null
|
||||
this.frustum = null
|
||||
this.setInterval1 = null
|
||||
this.webrtc = null
|
||||
|
||||
// 设置默认值
|
||||
Frustum.setDefaultValue(this)
|
||||
this.create()
|
||||
}
|
||||
|
||||
static setDefaultValue(that) {
|
||||
that.options.position = that.options.position || {}
|
||||
that.options.fov = that.options.fov || 30
|
||||
that.options.aspectRatio = that.options.aspectRatio || 1
|
||||
that.options.near = that.options.near || 1
|
||||
that.options.far = that.options.far || 120
|
||||
that.options.heading = that.options.heading || 0
|
||||
that.options.pitch = that.options.pitch || 90
|
||||
that.options.roll = that.options.roll || 0
|
||||
that.options.show = that.options.show ?? true
|
||||
that.options.videoUrl = that.options.videoUrl || ''
|
||||
that.options.index = that.options.index || 0
|
||||
that.options.arr = that.options.arr || []
|
||||
that.options.normalHeight = that.options.normalHeight || 100
|
||||
}
|
||||
|
||||
// 初始化视锥体
|
||||
create() {
|
||||
this.frustum = new Cesium.PerspectiveFrustum({
|
||||
fov: Cesium.Math.toRadians(this.options.fov),
|
||||
aspectRatio: this.options.aspectRatio,
|
||||
near: this.options.near,
|
||||
far: this.options.far
|
||||
})
|
||||
|
||||
const { lng, lat, alt } = this.options.position
|
||||
const { heading, pitch, roll } = this.options
|
||||
this.position = Cesium.Cartesian3.fromDegrees(
|
||||
lng,
|
||||
lat,
|
||||
alt + this.options.normalHeight
|
||||
)
|
||||
this.hpr = new Cesium.HeadingPitchRoll(
|
||||
Cesium.Math.toRadians(heading),
|
||||
Cesium.Math.toRadians(pitch),
|
||||
Cesium.Math.toRadians(roll)
|
||||
)
|
||||
|
||||
this.drawFrustumOutline()
|
||||
this.drawFrustumFilled()
|
||||
this.monitorKeyboard()
|
||||
this.updateFrustumSquareBase(40)
|
||||
this.syncHpr()
|
||||
if (this.options.videoUrl) {
|
||||
this.addVideoToFrustumTop2()
|
||||
}
|
||||
}
|
||||
|
||||
// 监听键盘事件
|
||||
monitorKeyboard() {
|
||||
const keyActions = {
|
||||
KeyQ: () => this.setIntervalhpr(-0.45),
|
||||
KeyE: () => this.setIntervalhpr(0.45),
|
||||
KeyB: () => this.setIntervalhprr(-0.45),
|
||||
KeyN: () => this.setIntervalhprr(0.45),
|
||||
KeyW: () => this.updateFrustumPosition('move', -0.00001),
|
||||
KeyS: () => this.updateFrustumPosition('move', 0.00001),
|
||||
KeyA: () => this.updateFrustumPosition('move', -0.00001, 0),
|
||||
KeyD: () => this.updateFrustumPosition('move', 0.00001, 0),
|
||||
KeyC: () => this.updateFrustumHeight(1), // 增加高度
|
||||
KeyZ: () => this.updateFrustumHeight(-1) // 降低高度
|
||||
}
|
||||
|
||||
this.keydownHandler = event => {
|
||||
if (keyActions[event.code]) keyActions[event.code]()
|
||||
}
|
||||
|
||||
this.keyupHandler = () => this.stopFrustumRotation()
|
||||
|
||||
document.addEventListener('keydown', this.keydownHandler)
|
||||
|
||||
document.addEventListener('keyup', this.keyupHandler)
|
||||
}
|
||||
// 渲染视频
|
||||
addVideoToFrustumTop() {
|
||||
// 创建视频元素
|
||||
const videoElement = document.createElement('video')
|
||||
videoElement.width = 640
|
||||
videoElement.height = 360
|
||||
videoElement.autoplay = true
|
||||
videoElement.loop = true
|
||||
videoElement.muted = true
|
||||
// videoElement.style.display = 'none'; // 隐藏视频元素
|
||||
document.body.appendChild(videoElement)
|
||||
|
||||
// 使用 flv.js 播放 FLV 视频
|
||||
if (flvjs.isSupported()) {
|
||||
const flvPlayer = flvjs.createPlayer({
|
||||
// url: 'http://zmkg.cqet.top:9991/live/2pUbcgTrly3mIDuxsDXN9h3hqcEKU6TlsV_YeIDyqHqXGzXafqWokXdU1q6j_S7hTCP7HynZQIsuNM6KQ5l-ag==.flv',
|
||||
type: 'flv',
|
||||
isLive: true,
|
||||
hasAudio: false,
|
||||
enableStashBuffer: true, //
|
||||
enableWorker: true,
|
||||
autoCleanupSourceBuffer: true, //自动清除缓存
|
||||
url: this.options.videoUrl
|
||||
})
|
||||
flvPlayer.attachMediaElement(videoElement)
|
||||
flvPlayer.load()
|
||||
flvPlayer.play()
|
||||
} else {
|
||||
console.error('FLV.js is not supported in this browser.')
|
||||
}
|
||||
|
||||
const corners = this.computeFrustumCorners(
|
||||
this.frustum,
|
||||
this.position,
|
||||
this.hpr
|
||||
)
|
||||
// 创建 PolygonGeometry 并应用视频作为纹理
|
||||
const polygonHierarchy = new Cesium.PolygonHierarchy([
|
||||
corners.bottomLeft,
|
||||
corners.bottomRight,
|
||||
corners.topRight,
|
||||
corners.topLeft
|
||||
])
|
||||
this.videoEntity = this.viewer.entities.add(
|
||||
new Cesium.Entity({
|
||||
id: '22222222',
|
||||
show: true,
|
||||
polygon: {
|
||||
hierarchy: polygonHierarchy
|
||||
}
|
||||
})
|
||||
)
|
||||
videoElement.addEventListener('loadeddata', () => {
|
||||
this.videoEntity.polygon.material = videoElement // 确保视频纹理加载后再设置
|
||||
})
|
||||
}
|
||||
// 渲染视频
|
||||
async addVideoToFrustumTop2() {
|
||||
// 创建视频元素
|
||||
const videoElement = document.createElement('video')
|
||||
videoElement.width = 640
|
||||
videoElement.height = 360
|
||||
videoElement.autoplay = true
|
||||
videoElement.loop = true
|
||||
videoElement.muted = true
|
||||
// videoElement.style.display = 'none'; // 隐藏视频元素
|
||||
document.body.appendChild(videoElement)
|
||||
await this.startPlay(videoElement, this.options.videoUrl)
|
||||
const corners = this.computeFrustumCorners(
|
||||
this.frustum,
|
||||
this.position,
|
||||
this.hpr
|
||||
)
|
||||
// 创建 PolygonGeometry 并应用视频作为纹理
|
||||
const polygonHierarchy = new Cesium.PolygonHierarchy([
|
||||
corners.bottomLeft,
|
||||
corners.bottomRight,
|
||||
corners.topRight,
|
||||
corners.topLeft
|
||||
])
|
||||
this.videoEntity = this.viewer.entities.add(
|
||||
new Cesium.Entity({
|
||||
id: '22222222',
|
||||
show: true,
|
||||
polygon: {
|
||||
hierarchy: polygonHierarchy
|
||||
}
|
||||
})
|
||||
)
|
||||
videoElement.addEventListener('loadeddata', () => {
|
||||
this.videoEntity.polygon.material = videoElement // 确保视频纹理加载后再设置
|
||||
})
|
||||
}
|
||||
async startPlay(element, url) {
|
||||
// Close existing SDK instance if any
|
||||
if (this.webrtc) {
|
||||
this.webrtc.close()
|
||||
}
|
||||
|
||||
// Initialize a new SDK instance
|
||||
this.webrtc = new SrsRtcWhipWhepAsync()
|
||||
|
||||
// Bind the video player to the SDK stream
|
||||
element.srcObject = this.webrtc.stream
|
||||
|
||||
try {
|
||||
const session = await this.webrtc.play(url)
|
||||
console.log(session)
|
||||
// this.sessionId = session.sessionid
|
||||
// this.simulatorUrl = `${session.simulator}?drop=1&username=${session.sessionid}`
|
||||
} catch (error) {
|
||||
// console.error('Error playing stream:', error)
|
||||
this.webrtc.close()
|
||||
// this.playerVisible = false
|
||||
}
|
||||
}
|
||||
// 计算视锥体远裁剪面(大面)的四个角点
|
||||
computeFrustumCorners(frustum, position, hpr) {
|
||||
const tanFov = Math.tan(frustum.fov * 0.5)
|
||||
const farHeight = frustum.far * tanFov
|
||||
const farWidth = farHeight * frustum.aspectRatio
|
||||
|
||||
const topLeft = new Cesium.Cartesian3(-farWidth, farHeight, -frustum.far)
|
||||
const topRight = new Cesium.Cartesian3(farWidth, farHeight, -frustum.far)
|
||||
const bottomLeft = new Cesium.Cartesian3(
|
||||
-farWidth,
|
||||
-farHeight,
|
||||
-frustum.far
|
||||
)
|
||||
const bottomRight = new Cesium.Cartesian3(
|
||||
farWidth,
|
||||
-farHeight,
|
||||
-frustum.far
|
||||
)
|
||||
const transform = Cesium.Transforms.headingPitchRollToFixedFrame(
|
||||
position,
|
||||
hpr
|
||||
)
|
||||
// console.log('transform111111111111111111111111', transform)
|
||||
return {
|
||||
topLeft: Cesium.Matrix4.multiplyByPoint(
|
||||
transform,
|
||||
topLeft,
|
||||
new Cesium.Cartesian3()
|
||||
),
|
||||
topRight: Cesium.Matrix4.multiplyByPoint(
|
||||
transform,
|
||||
topRight,
|
||||
new Cesium.Cartesian3()
|
||||
),
|
||||
bottomLeft: Cesium.Matrix4.multiplyByPoint(
|
||||
transform,
|
||||
bottomLeft,
|
||||
new Cesium.Cartesian3()
|
||||
),
|
||||
bottomRight: Cesium.Matrix4.multiplyByPoint(
|
||||
transform,
|
||||
bottomRight,
|
||||
new Cesium.Cartesian3()
|
||||
)
|
||||
}
|
||||
}
|
||||
// 封装的函数:更新 Polygon 面的位置
|
||||
updatePolygonPosition() {
|
||||
const corners = this.computeFrustumCorners(
|
||||
this.frustum,
|
||||
this.position,
|
||||
this.hpr
|
||||
)
|
||||
|
||||
this.videoEntity.polygon.hierarchy = new Cesium.CallbackProperty(e => {
|
||||
return new Cesium.PolygonHierarchy([
|
||||
corners.bottomLeft,
|
||||
corners.bottomRight,
|
||||
corners.topRight,
|
||||
corners.topLeft
|
||||
])
|
||||
})
|
||||
}
|
||||
// 更新锥体底部为正方形的方法
|
||||
updateFrustumSquareBase(value) {
|
||||
// 将输入值范围从 56 到 1 映射到面积范围 10000 到 100
|
||||
const minArea = 100 // 最小面积
|
||||
const maxArea = 10000 // 最大面积
|
||||
|
||||
// 映射公式(反转映射)
|
||||
const newArea = ((56 - value) / (56 - 1)) * (maxArea - minArea) + minArea
|
||||
|
||||
// 确保aspectRatio保持为1(正方形)
|
||||
this.frustum.aspectRatio = 1
|
||||
|
||||
// 根据面积计算正方形边长
|
||||
const sideLength = Math.sqrt(newArea)
|
||||
|
||||
// 远平面距离
|
||||
const far = this.frustum.far
|
||||
|
||||
// 计算新的fov
|
||||
const fov = 2 * Math.atan(sideLength / (2 * far))
|
||||
|
||||
// 更新视锥体的fov
|
||||
this.frustum.fov = fov
|
||||
|
||||
// 重新绘制视锥体轮廓和填充
|
||||
this.drawFrustumOutline()
|
||||
this.drawFrustumFilled()
|
||||
this.syncHpr()
|
||||
}
|
||||
updateFrustumHeight(deltaHeight) {
|
||||
const cartographic = Cesium.Cartographic.fromCartesian(this.position)
|
||||
cartographic.height += deltaHeight // 更新高度
|
||||
this.position = Cesium.Cartesian3.fromDegrees(
|
||||
Cesium.Math.toDegrees(cartographic.longitude),
|
||||
Cesium.Math.toDegrees(cartographic.latitude),
|
||||
cartographic.height
|
||||
)
|
||||
this.options.position.alt = cartographic.height
|
||||
// this.options.arr[
|
||||
// this.options.index
|
||||
// ] = this.viewer.scene.globe.ellipsoid.cartographicToCartesian(cartographic)
|
||||
this.syncHpr()
|
||||
this.drawFrustumOutline() // 重新绘制视锥体轮廓
|
||||
this.drawFrustumFilled()
|
||||
}
|
||||
// 更新position变化后的视锥体属性
|
||||
updatePositionHeight(p) {
|
||||
this.options.position = this.cartesian3Towgs84(p)
|
||||
this.syncHpr()
|
||||
this.drawFrustumOutline() // 重新绘制视锥体轮廓
|
||||
this.drawFrustumFilled()
|
||||
}
|
||||
cartesian3Towgs84(cartesian) {
|
||||
var ellipsoid = this.viewer.scene.globe.ellipsoid
|
||||
var cartesian3 = new Cesium.Cartesian3(
|
||||
cartesian.x,
|
||||
cartesian.y,
|
||||
cartesian.z
|
||||
)
|
||||
var cartographic = ellipsoid.cartesianToCartographic(cartesian3)
|
||||
var lat = Cesium.Math.toDegrees(cartographic.latitude)
|
||||
var lng = Cesium.Math.toDegrees(cartographic.longitude)
|
||||
var alt = cartographic.height < 0 ? 0 : cartographic.height
|
||||
return {
|
||||
lng: lng,
|
||||
lat: lat,
|
||||
alt: alt
|
||||
}
|
||||
}
|
||||
setIntervalhpr(num) {
|
||||
this.stopFrustumRotation() // 先停止当前的定时器
|
||||
this.setInterval1 = setInterval(() => {
|
||||
this.head += num
|
||||
this.updateFrustumHPR(Cesium.Math.toRadians(this.head), this.pitch)
|
||||
}, 10)
|
||||
}
|
||||
setIntervalhprr(num) {
|
||||
this.stopFrustumRotation() // 先停止当前的定时器
|
||||
this.setInterval1 = setInterval(() => {
|
||||
// 限制 pitch 在 [60, 180] 范围内
|
||||
this.pitch = Math.max(60, Math.min(180, this.pitch + num))
|
||||
this.updateFrustumHPR(this.head, Cesium.Math.toRadians(this.pitch))
|
||||
}, 10)
|
||||
}
|
||||
// 停止视锥体旋转
|
||||
stopFrustumRotation() {
|
||||
if (this.setInterval1) {
|
||||
clearInterval(this.setInterval1)
|
||||
this.setInterval1 = null
|
||||
}
|
||||
}
|
||||
// 新增:绘制填充的视锥体
|
||||
drawFrustumFilled() {
|
||||
let that = this
|
||||
// console.log('that.options.show', that.options.show)
|
||||
|
||||
const transform = Cesium.Transforms.headingPitchRollToFixedFrame(
|
||||
this.position,
|
||||
this.hpr
|
||||
)
|
||||
|
||||
const frustumGeometry = new Cesium.FrustumGeometry({
|
||||
frustum: this.frustum,
|
||||
origin: Cesium.Matrix4.getTranslation(transform, new Cesium.Cartesian3()),
|
||||
orientation: Cesium.Quaternion.fromRotationMatrix(
|
||||
Cesium.Matrix4.getRotation(transform, new Cesium.Matrix3())
|
||||
)
|
||||
})
|
||||
|
||||
if (this.currentFrustumFilled) {
|
||||
this.viewer.scene.primitives.remove(this.currentFrustumFilled)
|
||||
}
|
||||
|
||||
this.currentFrustumFilled = new Cesium.Primitive({
|
||||
geometryInstances: new Cesium.GeometryInstance({
|
||||
geometry: frustumGeometry,
|
||||
attributes: {
|
||||
color: Cesium.ColorGeometryInstanceAttribute.fromColor(
|
||||
Cesium.Color.fromAlpha(Cesium.Color.YELLOW, 0.4) // 半透明黄色填充
|
||||
)
|
||||
}
|
||||
}),
|
||||
appearance: new Cesium.MaterialAppearance({
|
||||
material: Cesium.Material.fromType('Color', {
|
||||
color: Cesium.Color.fromAlpha(Cesium.Color.YELLOW, 0.4) // 填充颜色
|
||||
}),
|
||||
translucent: true
|
||||
}),
|
||||
asynchronous: false,
|
||||
// show: false
|
||||
show: that.options.show
|
||||
})
|
||||
|
||||
this.viewer.scene.primitives.add(this.currentFrustumFilled)
|
||||
}
|
||||
// 绘制视锥体轮廓
|
||||
drawFrustumOutline() {
|
||||
let that = this
|
||||
// console.log('that.options.show', that.options.show)
|
||||
|
||||
const transform = Cesium.Transforms.headingPitchRollToFixedFrame(
|
||||
this.position,
|
||||
this.hpr
|
||||
)
|
||||
|
||||
const frustumOutlineGeometry = new Cesium.FrustumOutlineGeometry({
|
||||
frustum: this.frustum,
|
||||
origin: Cesium.Matrix4.getTranslation(transform, new Cesium.Cartesian3()),
|
||||
orientation: Cesium.Quaternion.fromRotationMatrix(
|
||||
Cesium.Matrix4.getRotation(transform, new Cesium.Matrix3())
|
||||
)
|
||||
})
|
||||
|
||||
if (this.currentFrustumOutline) {
|
||||
this.viewer.scene.primitives.remove(this.currentFrustumOutline)
|
||||
}
|
||||
|
||||
this.currentFrustumOutline = new Cesium.Primitive({
|
||||
geometryInstances: new Cesium.GeometryInstance({
|
||||
geometry: frustumOutlineGeometry,
|
||||
attributes: {
|
||||
color: Cesium.ColorGeometryInstanceAttribute.fromColor(
|
||||
Cesium.Color.YELLOW
|
||||
)
|
||||
}
|
||||
}),
|
||||
appearance: new Cesium.PolylineColorAppearance({
|
||||
translucent: false
|
||||
}),
|
||||
asynchronous: false,
|
||||
show: that.options.show
|
||||
// show: false
|
||||
})
|
||||
|
||||
this.viewer.scene.primitives.add(this.currentFrustumOutline)
|
||||
}
|
||||
// 更新视锥体位置
|
||||
updateFrustumPosition(type = 'move', p, deg = 90, flag = true) {
|
||||
if (type === 'move') {
|
||||
// eslint-disable-next-line no-undef
|
||||
const point = turf.point([
|
||||
this.options.position.lng,
|
||||
this.options.position.lat
|
||||
])
|
||||
const degreesValue = Cesium.Math.toDegrees(this.hpr.heading)
|
||||
const bearing = degreesValue + deg
|
||||
const options = { units: 'degrees' }
|
||||
// eslint-disable-next-line no-undef
|
||||
const destination = turf.destination(point, p, bearing, options).geometry
|
||||
.coordinates
|
||||
|
||||
this.position = Cesium.Cartesian3.fromDegrees(
|
||||
destination[0],
|
||||
destination[1],
|
||||
this.options.position.alt + this.options.normalHeight
|
||||
)
|
||||
this.options.position.lng = destination[0]
|
||||
this.options.position.lat = destination[1]
|
||||
|
||||
this.viewer.camera.setView({
|
||||
destination: Cesium.Cartesian3.fromDegrees(
|
||||
destination[0],
|
||||
destination[1],
|
||||
this.viewer.camera.positionCartographic.height
|
||||
)
|
||||
})
|
||||
}
|
||||
if (type === 'update') {
|
||||
this.position = p
|
||||
this.options.videoUrl && this.updatePolygonPosition()
|
||||
}
|
||||
if (flag) {
|
||||
this.syncHpr()
|
||||
this.updateFrustumAttributes()
|
||||
}
|
||||
}
|
||||
// 同步视角
|
||||
syncHpr() {
|
||||
// console.log('this.viewer1', this.viewer1);
|
||||
if (this.viewer1) {
|
||||
const { lng, lat, alt } = this.options.position
|
||||
let pitch = -this.hpr.pitch - Cesium.Math.toRadians(-90.0)
|
||||
this.viewer1.camera.setView({
|
||||
destination: Cesium.Cartesian3.fromDegrees(
|
||||
lng,
|
||||
lat,
|
||||
alt + this.options.normalHeight
|
||||
),
|
||||
orientation: {
|
||||
heading: this.hpr.heading + Cesium.Math.toRadians(-90.0),
|
||||
pitch,
|
||||
roll: this.hpr.roll
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
// 更新视锥体的 HeadingPitchRoll
|
||||
updateFrustumHPR(
|
||||
h = this.head,
|
||||
p = this.pitch,
|
||||
r = 0,
|
||||
flag = true,
|
||||
type = ''
|
||||
) {
|
||||
function degreesToRadians(degrees) {
|
||||
return (degrees * Math.PI) / 180.0
|
||||
}
|
||||
if (type == 'alone') {
|
||||
this.hpr.heading = degreesToRadians(h)
|
||||
this.hpr.pitch = degreesToRadians(p)
|
||||
this.hpr.roll = degreesToRadians(r)
|
||||
} else {
|
||||
this.hpr.heading = Cesium.Math.negativePiToPi(h)
|
||||
this.hpr.pitch = Cesium.Math.negativePiToPi(p)
|
||||
this.hpr.roll = Cesium.Math.negativePiToPi(r)
|
||||
}
|
||||
if (flag) {
|
||||
this.syncHpr()
|
||||
this.updateFrustumAttributes()
|
||||
}
|
||||
}
|
||||
// 用于更新
|
||||
updateFrustumAttributes() {
|
||||
let that = this
|
||||
// 检查 position 和 hpr 是否已初始化
|
||||
if (!this.position || !this.hpr) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('Position or HPR is not defined:', this.position, this.hpr)
|
||||
return
|
||||
}
|
||||
|
||||
// 生成变换矩阵
|
||||
const transform = Cesium.Transforms.headingPitchRollToFixedFrame(
|
||||
this.position,
|
||||
this.hpr
|
||||
)
|
||||
|
||||
if (!transform) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('Transform generation failed.')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
// 准备轮廓几何体和外观
|
||||
const outlineGeometry = new Cesium.FrustumOutlineGeometry({
|
||||
frustum: this.frustum,
|
||||
origin: Cesium.Matrix4.getTranslation(
|
||||
transform,
|
||||
new Cesium.Cartesian3()
|
||||
),
|
||||
orientation: Cesium.Quaternion.fromRotationMatrix(
|
||||
Cesium.Matrix4.getRotation(transform, new Cesium.Matrix3())
|
||||
)
|
||||
})
|
||||
|
||||
const outlineAppearance = new Cesium.PolylineColorAppearance({
|
||||
translucent: false
|
||||
})
|
||||
const outlineColor = Cesium.ColorGeometryInstanceAttribute.fromColor(
|
||||
Cesium.Color.YELLOW
|
||||
)
|
||||
|
||||
// 准备填充几何体和外观
|
||||
const filledGeometry = new Cesium.FrustumGeometry({
|
||||
frustum: this.frustum,
|
||||
origin: Cesium.Matrix4.getTranslation(
|
||||
transform,
|
||||
new Cesium.Cartesian3()
|
||||
),
|
||||
orientation: Cesium.Quaternion.fromRotationMatrix(
|
||||
Cesium.Matrix4.getRotation(transform, new Cesium.Matrix3())
|
||||
)
|
||||
})
|
||||
|
||||
const filledAppearance = new Cesium.MaterialAppearance({
|
||||
material: Cesium.Material.fromType('Color', {
|
||||
color: Cesium.Color.YELLOW.withAlpha(0.5)
|
||||
}),
|
||||
translucent: true
|
||||
})
|
||||
const filledColor = Cesium.ColorGeometryInstanceAttribute.fromColor(
|
||||
Cesium.Color.RED.withAlpha(0.5)
|
||||
)
|
||||
|
||||
// 删除旧的 Primitive
|
||||
if (this.currentFrustumOutline) {
|
||||
this.viewer.scene.primitives.remove(this.currentFrustumOutline)
|
||||
}
|
||||
if (this.currentFrustumFilled) {
|
||||
this.viewer.scene.primitives.remove(this.currentFrustumFilled)
|
||||
}
|
||||
|
||||
// 创建并添加新的轮廓 Primitive
|
||||
this.currentFrustumOutline = new Cesium.Primitive({
|
||||
geometryInstances: new Cesium.GeometryInstance({
|
||||
geometry: outlineGeometry,
|
||||
attributes: { color: outlineColor }
|
||||
}),
|
||||
appearance: outlineAppearance,
|
||||
asynchronous: false,
|
||||
show: that.options.show
|
||||
})
|
||||
this.viewer.scene.primitives.add(this.currentFrustumOutline)
|
||||
|
||||
// 创建并添加新的填充 Primitive
|
||||
this.currentFrustumFilled = new Cesium.Primitive({
|
||||
geometryInstances: new Cesium.GeometryInstance({
|
||||
geometry: filledGeometry,
|
||||
attributes: { color: filledColor }
|
||||
}),
|
||||
appearance: filledAppearance,
|
||||
asynchronous: false,
|
||||
show: that.options.show
|
||||
})
|
||||
this.viewer.scene.primitives.add(this.currentFrustumFilled)
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('Error in drawFrustum:', error)
|
||||
}
|
||||
}
|
||||
// 调整视锥体的 near 和 far 平面
|
||||
updateFrustumNearFar(newNear, newFar) {
|
||||
this.frustum.near = newNear
|
||||
this.frustum.far = newFar
|
||||
this.drawFrustumOutline()
|
||||
this.drawFrustumFilled()
|
||||
}
|
||||
// 调整视锥体的 fov
|
||||
updateFrustumFov(newFov) {
|
||||
this.frustum.fov = Cesium.Math.toRadians(newFov)
|
||||
this.drawFrustumOutline()
|
||||
this.drawFrustumFilled()
|
||||
}
|
||||
|
||||
get show() {
|
||||
return this.options.show
|
||||
}
|
||||
|
||||
set show(bool) {
|
||||
if (typeof bool === 'boolean') {
|
||||
this.options.show = bool
|
||||
this.currentFrustumOutline.show = bool
|
||||
this.currentFrustumFilled.show = bool
|
||||
}
|
||||
}
|
||||
|
||||
remove() {
|
||||
document.removeEventListener('keydown', this.keydownHandler)
|
||||
document.removeEventListener('keyup', this.keyupHandler)
|
||||
if (this.currentFrustumFilled) {
|
||||
this.viewer.scene.primitives.remove(this.currentFrustumFilled)
|
||||
}
|
||||
if (this.currentFrustumOutline) {
|
||||
this.viewer.scene.primitives.remove(this.currentFrustumOutline)
|
||||
}
|
||||
if (this.videoEntity) {
|
||||
this.viewer.entities.remove(this.videoEntity)
|
||||
}
|
||||
}
|
||||
}
|
||||
257
src/Obj/AirLine/frustum2.js
Normal file
257
src/Obj/AirLine/frustum2.js
Normal file
@ -0,0 +1,257 @@
|
||||
export default class FRUSTUN {
|
||||
constructor(options, viewer, viewer1) {
|
||||
this.options = { ...options }
|
||||
this.viewer = viewer
|
||||
this.viewer1 = viewer1
|
||||
this.head = 0
|
||||
this.po = 0.00001
|
||||
this.position = null
|
||||
this.hpr = null
|
||||
this.currentFrustumOutline = null
|
||||
this.frustum = null
|
||||
this.setInterval = null
|
||||
FRUSTUN.setDefaultValue(this)
|
||||
this.create()
|
||||
}
|
||||
static setDefaultValue(that) {
|
||||
that.options.position = that.options.position || {}
|
||||
that.options.fov = that.options.fov || 20
|
||||
that.options.aspectRatio = that.options.aspectRatio || 1
|
||||
that.options.near = that.options.near || 1
|
||||
that.options.far = that.options.far || 100
|
||||
that.options.heading = that.options.heading || 0
|
||||
that.options.pitch = that.options.pitch || 90
|
||||
that.options.roll = that.options.roll || 0
|
||||
that.options.show = that.options.show || true
|
||||
}
|
||||
// 初始化视锥体
|
||||
create() {
|
||||
this.frustum = new Cesium.PerspectiveFrustum()
|
||||
this.frustum.fov = Cesium.Math.toRadians(this.options.fov)
|
||||
this.frustum.aspectRatio = 1.0 // 保持 aspectRatio 不变
|
||||
this.frustum.near = 1.0
|
||||
this.frustum.far = 50.0
|
||||
// 设置初始视锥体位置和方向
|
||||
let { lng, lat, alt } = this.options.position
|
||||
let { heading, pitch, roll } = this.options
|
||||
this.position = Cesium.Cartesian3.fromDegrees(lng, lat, alt + 100)
|
||||
this.hpr = new Cesium.HeadingPitchRoll(
|
||||
Cesium.Math.toRadians(heading),
|
||||
Cesium.Math.toRadians(pitch),
|
||||
Cesium.Math.toRadians(roll)
|
||||
)
|
||||
console.log(heading)
|
||||
this.drawFrustumOutline()
|
||||
this.monitorKeyboard()
|
||||
}
|
||||
|
||||
setIntervalhpr(num) {
|
||||
if (!this.setInterval1) {
|
||||
this.setInterval1 = setInterval(() => {
|
||||
this.head += num
|
||||
this.updateFrustumHPR(Cesium.Math.toRadians(this.head))
|
||||
}, 10)
|
||||
}
|
||||
}
|
||||
// 监听 键盘事件
|
||||
// monitorKeyboard() {
|
||||
// let that = this;
|
||||
// document.addEventListener("keydown", function (event) {
|
||||
// switch (event.code) {
|
||||
// case "KeyQ":
|
||||
// that.setIntervalhpr(-0.45);
|
||||
// break;
|
||||
// case "KeyE":
|
||||
// that.setIntervalhpr(0.45);
|
||||
// break;
|
||||
// case "KeyW":
|
||||
// that.updateFrustumPosition("move", -0.00001);
|
||||
// break;
|
||||
// case "KeyS":
|
||||
// that.updateFrustumPosition("move", 0.00001);
|
||||
// break;
|
||||
// case "KeyA":
|
||||
// that.updateFrustumPosition("move", -0.00001, 0);
|
||||
// break;
|
||||
// case "KeyD":
|
||||
// that.updateFrustumPosition("move", 0.00001, 0);
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
// });
|
||||
// document.addEventListener("keyup", function (event) {
|
||||
// clearInterval(that.setInterval1);
|
||||
// that.setInterval1 = null; // 重置 interval
|
||||
// });
|
||||
// }
|
||||
// 监听键盘事件
|
||||
monitorKeyboard() {
|
||||
const keyActions = {
|
||||
KeyQ: () => this.setIntervalhpr(-0.45),
|
||||
KeyE: () => this.setIntervalhpr(0.45),
|
||||
KeyW: () => this.updateFrustumPosition('move', -0.00001),
|
||||
KeyS: () => this.updateFrustumPosition('move', 0.00001),
|
||||
KeyA: () => this.updateFrustumPosition('move', -0.00001, 0),
|
||||
KeyD: () => this.updateFrustumPosition('move', 0.00001, 0),
|
||||
KeyC: () => this.updateFrustumHeight(1), // 增加高度
|
||||
KeyZ: () => this.updateFrustumHeight(-1) // 降低高度
|
||||
}
|
||||
|
||||
document.addEventListener('keydown', event => {
|
||||
if (keyActions[event.code]) keyActions[event.code]()
|
||||
})
|
||||
|
||||
document.addEventListener('keyup', () => this.stopFrustumRotation())
|
||||
}
|
||||
// 停止视锥体旋转
|
||||
stopFrustumRotation() {
|
||||
clearInterval(this.setInterval1)
|
||||
this.setInterval1 = null
|
||||
}
|
||||
// 使用 HeadingPitchRoll 创建视锥体轮廓
|
||||
drawFrustumOutline() {
|
||||
const transform = Cesium.Transforms.headingPitchRollToFixedFrame(
|
||||
this.position,
|
||||
this.hpr
|
||||
)
|
||||
const frustumOutlineGeometry = new Cesium.FrustumOutlineGeometry({
|
||||
frustum: this.frustum,
|
||||
origin: Cesium.Matrix4.getTranslation(transform, new Cesium.Cartesian3()),
|
||||
orientation: Cesium.Quaternion.fromRotationMatrix(
|
||||
Cesium.Matrix4.getRotation(transform, new Cesium.Matrix3())
|
||||
)
|
||||
})
|
||||
|
||||
if (this.currentFrustumOutline) {
|
||||
this.viewer.scene.primitives.remove(this.currentFrustumOutline)
|
||||
}
|
||||
|
||||
this.currentFrustumOutline = new Cesium.Primitive({
|
||||
geometryInstances: new Cesium.GeometryInstance({
|
||||
geometry: frustumOutlineGeometry,
|
||||
attributes: {
|
||||
color: Cesium.ColorGeometryInstanceAttribute.fromColor(
|
||||
Cesium.Color.YELLOW
|
||||
)
|
||||
}
|
||||
}),
|
||||
appearance: new Cesium.PolylineColorAppearance({
|
||||
translucent: false
|
||||
}),
|
||||
asynchronous: false
|
||||
})
|
||||
|
||||
this.viewer.scene.primitives.add(this.currentFrustumOutline)
|
||||
}
|
||||
// 更新视锥体位置
|
||||
updateFrustumPosition(type = 'move', p, deg = 90) {
|
||||
if (type == 'move') {
|
||||
var point = turf.point([
|
||||
this.options.position.lng,
|
||||
this.options.position.lat
|
||||
])
|
||||
const degreesValue = Cesium.Math.toDegrees(this.hpr.heading)
|
||||
var distance = p
|
||||
var bearing = degreesValue + deg
|
||||
var options = { units: 'degrees' }
|
||||
|
||||
var destination = turf.destination(point, distance, bearing, options)
|
||||
.geometry.coordinates
|
||||
this.position = Cesium.Cartesian3.fromDegrees(
|
||||
destination[0],
|
||||
destination[1],
|
||||
this.options.position.alt + 100
|
||||
)
|
||||
this.options.position.lng = destination[0]
|
||||
this.options.position.lat = destination[1]
|
||||
|
||||
this.viewer.camera.setView({
|
||||
destination: Cesium.Cartesian3.fromDegrees(
|
||||
destination[0],
|
||||
destination[1],
|
||||
this.viewer.camera.positionCartographic.height
|
||||
),
|
||||
orientation: {
|
||||
heading: this.viewer.camera.heading,
|
||||
pitch: this.viewer.camera.pitch,
|
||||
roll: this.viewer.camera.roll
|
||||
}
|
||||
})
|
||||
}
|
||||
if (type == 'update') {
|
||||
this.position = p
|
||||
}
|
||||
// this.tongbuHpr();
|
||||
this.drawFrustumOutline()
|
||||
}
|
||||
// 同步视角
|
||||
tongbuHpr() {
|
||||
const { lng, lat, alt } = this.options.position
|
||||
this.viewer1.camera.setView({
|
||||
destination: new Cesium.Cartesian3.fromDegrees(lng, lat, alt + 100),
|
||||
orientation: {
|
||||
heading: this.hpr.heading + Cesium.Math.toRadians(-90.0),
|
||||
pitch: this.hpr.pitch + Cesium.Math.toRadians(-90.0),
|
||||
roll: this.hpr.roll
|
||||
}
|
||||
})
|
||||
}
|
||||
updateFrustumHeight(deltaHeight) {
|
||||
const cartographic = Cesium.Cartographic.fromCartesian(this.position)
|
||||
cartographic.height += deltaHeight // 更新高度
|
||||
this.position = Cesium.Cartesian3.fromDegrees(
|
||||
Cesium.Math.toDegrees(cartographic.longitude),
|
||||
Cesium.Math.toDegrees(cartographic.latitude),
|
||||
cartographic.height
|
||||
)
|
||||
this.options.position.alt = cartographic.height
|
||||
// this.tongbuHpr();
|
||||
this.drawFrustumOutline() // 重新绘制视锥体轮廓
|
||||
}
|
||||
// 更新视锥体的 HeadingPitchRoll
|
||||
updateFrustumHPR(h = 0, p = Cesium.Math.toRadians(90), r = 0) {
|
||||
this.hpr.heading = Cesium.Math.negativePiToPi(h)
|
||||
this.hpr.pitch = Cesium.Math.negativePiToPi(p)
|
||||
this.hpr.roll = Cesium.Math.negativePiToPi(r)
|
||||
// this.tongbuHpr();
|
||||
this.drawFrustumOutline()
|
||||
}
|
||||
// 封装的函数:调整视锥体的 near 和 far 平面
|
||||
updateFrustumNearFar(newNear, newFar) {
|
||||
this.frustum.near = newNear
|
||||
this.frustum.far = newFar
|
||||
this.drawFrustumOutline()
|
||||
}
|
||||
// 封装的函数:调整视锥体的 fov(远裁剪面的大小)
|
||||
updateFrustumFov(newFov) {
|
||||
this.frustum.fov = Cesium.Math.toRadians(newFov)
|
||||
this.drawFrustumOutline()
|
||||
this.viewer.scene.requestRender() // 强制重新渲染场景
|
||||
}
|
||||
// 封装的函数:调整视锥体的高度
|
||||
updateFrustumHeight(deltaHeight) {
|
||||
const cartographic = Cesium.Cartographic.fromCartesian(this.position)
|
||||
cartographic.height += deltaHeight
|
||||
this.position = Cesium.Cartesian3.fromDegrees(
|
||||
Cesium.Math.toDegrees(cartographic.longitude),
|
||||
Cesium.Math.toDegrees(cartographic.latitude),
|
||||
cartographic.height
|
||||
)
|
||||
this.drawFrustumOutline()
|
||||
this.viewer.scene.requestRender() // 强制重新渲染场景
|
||||
}
|
||||
get show() {
|
||||
return this.options.show
|
||||
}
|
||||
set show(bool) {
|
||||
if (typeof bool == 'boolean') {
|
||||
this.currentFrustumOutline.show = bool
|
||||
}
|
||||
}
|
||||
remove() {
|
||||
if (this.currentFrustumOutline) {
|
||||
this.viewer.scene.primitives.remove(this.currentFrustumOutline)
|
||||
}
|
||||
}
|
||||
}
|
||||
290
src/Obj/AirLine/index.js
Normal file
290
src/Obj/AirLine/index.js
Normal file
@ -0,0 +1,290 @@
|
||||
import { closeRotateAround, closeViewFollow} from '../../Global/global'
|
||||
export default class AirLine {
|
||||
constructor(options, earth) {
|
||||
this.earth = earth
|
||||
this.positions = null
|
||||
this.options = { ...options }
|
||||
this.Model = null
|
||||
this.pointCollection = null
|
||||
this.entity = null
|
||||
this.dataSouce = new Cesium.CustomDataSource('airLineSource' + options.id)
|
||||
AirLine.setDefaultValue(this)
|
||||
AirLine.add(this)
|
||||
}
|
||||
static setDefaultValue(that) {
|
||||
that.options.id = that.options.id || Cesium.createGuid()
|
||||
that.options.positions = that.options.positions || []
|
||||
that.options.width = that.options.width || 5
|
||||
that.options.show = that.options.show || true
|
||||
that.options.color = that.options.color || '#00FFFF'
|
||||
that.options.height = that.options.height || 20
|
||||
that.options.url = that.options.url || ''
|
||||
that.options.modelShow = that.options.modelShow || false
|
||||
that.options.flag = that.options.flag || true
|
||||
that.options.speed = that.options.speed || 1
|
||||
that.options.billboard.show = that.options.billboard.show || true
|
||||
that.options.billboard.image = that.options.billboard.image || ''
|
||||
that.options.billboard.scale = that.options.billboard.scale || 1
|
||||
that.options.billboard.width = that.options.billboard.width || 64
|
||||
that.options.billboard.height = that.options.billboard.height || 64
|
||||
that.options.billboard.near = that.options.billboard.near ?? 1000
|
||||
that.options.billboard.far = that.options.billboard.far ?? 10000
|
||||
}
|
||||
static add(that) {
|
||||
if (that.options.positions.length < 3) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn('坐标数量至少需要3个')
|
||||
return
|
||||
}
|
||||
that.pointCollection = that.earth.viewer.scene.primitives.add(
|
||||
new Cesium.PointPrimitiveCollection()
|
||||
)
|
||||
for (let i = 0; i < that.options.positions.length - 1; i++) {
|
||||
let entity = that.createLine([
|
||||
that.options.positions[i],
|
||||
that.options.positions[i + 1]
|
||||
])
|
||||
that.dataSouce.entities.add(entity)
|
||||
}
|
||||
that.earth.viewer.dataSources.add(that.dataSouce).then(r => {})
|
||||
that.createPoint()
|
||||
that.createModel()
|
||||
}
|
||||
// 创建线条
|
||||
createLine(positions) {
|
||||
let entity = new Cesium.Entity({
|
||||
id: Cesium.createGuid(),
|
||||
polyline: {
|
||||
positions: positions,
|
||||
clampToGround: false,
|
||||
width: this.options.width,
|
||||
material: new Cesium.PolylineArrowMaterialProperty(
|
||||
Cesium.Color.fromCssColorString(this.options.color)
|
||||
),
|
||||
zIndex: 99999999
|
||||
},
|
||||
show: true,
|
||||
})
|
||||
return entity
|
||||
}
|
||||
// 生成点
|
||||
createPoint() {
|
||||
this.options.positions.forEach((item, index) => {
|
||||
this.pointCollection.add({
|
||||
show: true,
|
||||
position: item,
|
||||
pixelSize: 10.0,
|
||||
color: Cesium.Color.GREENYELLOW,
|
||||
id: index
|
||||
})
|
||||
})
|
||||
}
|
||||
get show() {
|
||||
return this.entity.show
|
||||
}
|
||||
set show(status) {
|
||||
if (typeof status == 'boolean') this.entity.show = status
|
||||
}
|
||||
get modelShow() {
|
||||
return this.Model.show
|
||||
}
|
||||
set modelShow(status) {
|
||||
if (typeof status == 'boolean') this.Model.show = status
|
||||
}
|
||||
// 添加一个模型
|
||||
createModel() {
|
||||
let scaleByDistance = new Cesium.NearFarScalar(
|
||||
this.options.billboard.near,
|
||||
1,
|
||||
this.options.billboard.far,
|
||||
0
|
||||
)
|
||||
const position = this.options.positions[0]
|
||||
const heading = Cesium.Math.toRadians(0)
|
||||
const pitch = 0
|
||||
const roll = 0
|
||||
const hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll)
|
||||
const orientation = Cesium.Transforms.headingPitchRollQuaternion(
|
||||
position,
|
||||
hpr
|
||||
)
|
||||
this.Model = this.earth.viewer.entities.add({
|
||||
name: this.options.billboard.image,
|
||||
position,
|
||||
// orientation,
|
||||
billboard: {
|
||||
show: this.options.billboard.show,
|
||||
image: this.options.billboard.image,
|
||||
scale: this.options.billboard.scale,
|
||||
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
||||
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
width: this.options.billboard.width,
|
||||
height: this.options.billboard.height,
|
||||
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
||||
scaleByDistance,
|
||||
pixelOffsetScaleByDistance: scaleByDistance
|
||||
},
|
||||
// model: {
|
||||
// uri: this.options.url,
|
||||
// minimumPixelSize: 128,
|
||||
// maximumScale: 20000
|
||||
// },
|
||||
show: this.options.modelShow
|
||||
})
|
||||
}
|
||||
// 开始飞行
|
||||
start() {
|
||||
if (!this.options.positions) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn('请先绘制并且生成航线')
|
||||
return
|
||||
}
|
||||
let i
|
||||
let that = this
|
||||
this.timer = setInterval(function() {
|
||||
if (this.index) {
|
||||
i = this.index
|
||||
} else {
|
||||
i = 0
|
||||
}
|
||||
i++
|
||||
this.index = i
|
||||
if (i > that.options.positions.length) {
|
||||
clearInterval(this.timer)
|
||||
} else {
|
||||
let position = that.options.positions[i]
|
||||
if (position) {
|
||||
that.Model.position = new Cesium.CallbackProperty(e => {
|
||||
return position
|
||||
})
|
||||
that.Model.orientation = that.direction(
|
||||
that.options.positions[i - 1],
|
||||
that.options.positions[i]
|
||||
).orientation
|
||||
}
|
||||
}
|
||||
}, 100)
|
||||
}
|
||||
// 停止飞行
|
||||
stop() {
|
||||
if (this.timer) {
|
||||
clearInterval(this.timer)
|
||||
}
|
||||
}
|
||||
// 飞入
|
||||
flyTo() {
|
||||
closeRotateAround(this.earth)
|
||||
closeViewFollow(this.earth)
|
||||
let positionArray = []
|
||||
for (let i = 0; i < this.options.positions.length; i++) {
|
||||
let item = this.options.positions[i]
|
||||
positionArray.push(item.x, item.y, item.z)
|
||||
}
|
||||
// console.log('cartesian',cartesian);
|
||||
// let position = Cesium.Cartographic.fromCartesian(cartesian)
|
||||
// console.log('position',position);
|
||||
let BoundingSphere = Cesium.BoundingSphere.fromVertices(positionArray)
|
||||
this.earth.viewer.camera.flyToBoundingSphere(BoundingSphere, {
|
||||
offset: {
|
||||
heading: Cesium.Math.toRadians(0.0),
|
||||
pitch: Cesium.Math.toRadians(-90.0),
|
||||
roll: Cesium.Math.toRadians(0.0)
|
||||
}
|
||||
})
|
||||
}
|
||||
// 计算一个到另一个点的方向
|
||||
direction(pointA, pointB) {
|
||||
//向量AB
|
||||
const vector2 = Cesium.Cartesian3.subtract(
|
||||
pointB,
|
||||
pointA,
|
||||
new Cesium.Cartesian3()
|
||||
)
|
||||
//归一化
|
||||
const normal = Cesium.Cartesian3.normalize(vector2, new Cesium.Cartesian3())
|
||||
//旋转矩阵 rotationMatrixFromPositionVelocity源码中有,并未出现在cesiumAPI中
|
||||
const rotationMatrix3 = Cesium.Transforms.rotationMatrixFromPositionVelocity(
|
||||
pointA,
|
||||
normal,
|
||||
Cesium.Ellipsoid.WGS84
|
||||
)
|
||||
const modelMatrix4 = Cesium.Matrix4.fromRotationTranslation(
|
||||
rotationMatrix3,
|
||||
pointA
|
||||
)
|
||||
// 获取getHeadingPitchRoll
|
||||
let m1 = Cesium.Transforms.eastNorthUpToFixedFrame(
|
||||
Cesium.Matrix4.getTranslation(modelMatrix4, new Cesium.Cartesian3()),
|
||||
Cesium.Ellipsoid.WGS84,
|
||||
new Cesium.Matrix4()
|
||||
)
|
||||
// 矩阵相除
|
||||
let m3 = Cesium.Matrix4.multiply(
|
||||
Cesium.Matrix4.inverse(m1, new Cesium.Matrix4()),
|
||||
modelMatrix4,
|
||||
new Cesium.Matrix4()
|
||||
)
|
||||
// 得到旋转矩阵
|
||||
let mat3 = Cesium.Matrix4.getMatrix3(m3, new Cesium.Matrix3())
|
||||
// 计算四元数
|
||||
let q = Cesium.Quaternion.fromRotationMatrix(mat3)
|
||||
// 计算旋转角(弧度)
|
||||
let hpr = Cesium.HeadingPitchRoll.fromQuaternion(q)
|
||||
// hpr.pitch = hpr.pitch + 3.14 / 2 + 3.14;
|
||||
hpr.pitch = 0
|
||||
let orientation = Cesium.Transforms.headingPitchRollQuaternion(pointA, hpr)
|
||||
return { hpr, orientation }
|
||||
}
|
||||
// 删除
|
||||
remove() {
|
||||
this.earth.viewer.entities.remove(this.entity)
|
||||
this.dataSouce.entities.removeAll()
|
||||
this.pointCollection && this.pointCollection.destroy()
|
||||
this.Model && this.earth.viewer.entities.remove(this.Model)
|
||||
this.timer && clearInterval(this.timer)
|
||||
this.timer = null
|
||||
}
|
||||
// 返回照片数量 航点数
|
||||
getInfo() {
|
||||
return {
|
||||
length: this.countLength(),
|
||||
time: this.countTime(),
|
||||
waypoint: this.options.positions.length,
|
||||
photos: this.options.positions.length
|
||||
}
|
||||
}
|
||||
//计算航线得长度
|
||||
countLength() {
|
||||
let totalDistance = 0
|
||||
for (let i = 0; i < this.options.positions.length - 1; i++) {
|
||||
const start = this.options.positions[i]
|
||||
const end = this.options.positions[i + 1]
|
||||
const distance = Cesium.Cartesian3.distance(start, end)
|
||||
totalDistance += distance
|
||||
}
|
||||
return totalDistance.toFixed(2) // 返回保留两位小数的距离
|
||||
}
|
||||
//计算航线时间
|
||||
countTime() {
|
||||
let time = Math.floor(Number(this.countLength())) / this.options.speed
|
||||
let s = Math.floor(time % 60)
|
||||
let m = Math.floor(time / 60)
|
||||
let str = m + '分' + s + '秒'
|
||||
return str
|
||||
}
|
||||
//显示隐藏
|
||||
isShow(status) {
|
||||
if (typeof status === 'boolean') {
|
||||
this.modelShow = status
|
||||
this.dataSouce.show = status
|
||||
let len = this.pointCollection.length
|
||||
for (let i = 0; i < len; ++i) {
|
||||
let p = this.pointCollection.get(i)
|
||||
p.show = status
|
||||
}
|
||||
} else {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('参数须为Boolean类型!')
|
||||
}
|
||||
}
|
||||
}
|
||||
359
src/Obj/AirLine/pointRoute.js
Normal file
359
src/Obj/AirLine/pointRoute.js
Normal file
@ -0,0 +1,359 @@
|
||||
import FRUSTUN from './frustum.js'
|
||||
import BillordPointLine from './billord_point_line'
|
||||
|
||||
export default class PointRoute {
|
||||
constructor(options = {}, viewer, viewer1) {
|
||||
this.options = { ...options }
|
||||
this.viewer = viewer
|
||||
this.viewer1 = viewer1
|
||||
this.entity = null
|
||||
this.frustum = null
|
||||
this.billordPointLineMaps = []
|
||||
this.index = 0
|
||||
this.positions = []
|
||||
PointRoute.setDefaultValue(this)
|
||||
this.create()
|
||||
}
|
||||
static setDefaultValue(that) {
|
||||
that.options.positions = that.options.positions || []
|
||||
that.options.show = that.options.show || true
|
||||
that.options.color = that.options.color || '#00d590'
|
||||
that.options.height = that.options.height || 500
|
||||
that.options.speed = that.options.speed || 1
|
||||
that.options.frustumShow = that.options.frustumShow ?? true
|
||||
that.options.saveFun = that.options.saveFun || null
|
||||
that.options.selectFun = that.options.selectFun || null
|
||||
that.options.keyboard = that.options.keyboard ?? true
|
||||
that.options.normalHeight = that.options.normalHeight || 100
|
||||
that.options.airHeight = that.options.airHeight || 100
|
||||
}
|
||||
create() {
|
||||
if (this.options.positions.length < 2) {
|
||||
return
|
||||
}
|
||||
let that = this
|
||||
let { frustumShow } = that.options
|
||||
this.entity = this.viewer.entities.add({
|
||||
show: this.options.show,
|
||||
polyline: {
|
||||
positions: new Cesium.CallbackProperty(() => {
|
||||
let positions = []
|
||||
for (let i = 0; i < this.billordPointLineMaps.length; i++) {
|
||||
const element = this.billordPointLineMaps[i]
|
||||
positions.push(element.billboardEntity.position.getValue())
|
||||
}
|
||||
return positions
|
||||
}, false),
|
||||
width: 3,
|
||||
material: Cesium.Color.fromCssColorString(this.options.color)
|
||||
}
|
||||
})
|
||||
// 创建点、线、billbord
|
||||
for (let i = 0; i < this.options.positions.length; i++) {
|
||||
const element = this.options.positions[i]
|
||||
// console.log("elementelementelement", element);
|
||||
if (frustumShow && i == this.index) {
|
||||
this.frustum = new FRUSTUN(
|
||||
{
|
||||
position: element,
|
||||
show: false,
|
||||
arr: this.options.positions,
|
||||
index: i,
|
||||
normalHeight: this.options.normalHeight
|
||||
},
|
||||
this.viewer,
|
||||
this.viewer1
|
||||
)
|
||||
}
|
||||
let op = new BillordPointLine(
|
||||
{
|
||||
positions: element,
|
||||
index: i + 1,
|
||||
saveFun: that.options.saveFun,
|
||||
selectFun: that.options.selectFun,
|
||||
keyboard: that.options.keyboard,
|
||||
updateFrustumFun: that.updateFrustumPosition,
|
||||
normalHeight: that.options.normalHeight,
|
||||
frustum: that.frustum,
|
||||
airHeight: that.options.airHeight
|
||||
},
|
||||
this.viewer
|
||||
)
|
||||
this.billordPointLineMaps.push(op)
|
||||
}
|
||||
this.onKey()
|
||||
}
|
||||
get show() {
|
||||
return this.options.show
|
||||
}
|
||||
set show(bool) {
|
||||
if (typeof bool === 'boolean') {
|
||||
this.frustum.currentFrustumOutline.show = bool
|
||||
this.billordPointLineMaps.forEach(item => {
|
||||
item.show = bool
|
||||
})
|
||||
this.entity.show = bool
|
||||
}
|
||||
}
|
||||
// 监听键盘事件
|
||||
onKey() {
|
||||
let that = this
|
||||
document.addEventListener('keydown', function(event) {
|
||||
switch (event.key) {
|
||||
case 'ArrowUp':
|
||||
that.index += 1
|
||||
that.updateFrustum(true)
|
||||
break
|
||||
case 'ArrowDown':
|
||||
that.index -= 1
|
||||
that.updateFrustum(false)
|
||||
break
|
||||
}
|
||||
})
|
||||
}
|
||||
// 更新frustum
|
||||
updateFrustum(flag) {
|
||||
console.log(this.index)
|
||||
let obj
|
||||
if (this.index > this.options.positions.length - 1 || this.index < 0) {
|
||||
let str = this.index > 0 ? '已选中最后一个航点' : '已选中第一个航点'
|
||||
alert(str)
|
||||
return
|
||||
}
|
||||
for (let i = 0; i < this.billordPointLineMaps.length; i++) {
|
||||
const element = this.billordPointLineMaps[i]
|
||||
const hpr = null
|
||||
if (i == this.index) {
|
||||
let position = element.billboardEntity.position.getValue()
|
||||
if (this.index !== 0) {
|
||||
obj = this.direction(
|
||||
this.billordPointLineMaps[
|
||||
i - 1
|
||||
].billboardEntity.position.getValue(),
|
||||
element.billboardEntity.position.getValue()
|
||||
)
|
||||
hpr = obj.hpr
|
||||
}
|
||||
if (this.index == 0) {
|
||||
obj = this.direction(
|
||||
this.billordPointLineMaps[0].billboardEntity.position.getValue(),
|
||||
this.billordPointLineMaps[1].billboardEntity.position.getValue()
|
||||
)
|
||||
hpr = obj.hpr
|
||||
}
|
||||
if (hpr) {
|
||||
this.frustum.updateFrustumHPR(
|
||||
hpr.heading,
|
||||
this.frustum.pitch,
|
||||
hpr.roll
|
||||
)
|
||||
}
|
||||
if (position) {
|
||||
this.frustum.updateFrustumPosition('update', position)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cartesian3Towgs84(cartesian) {
|
||||
var ellipsoid = this.viewer.scene.globe.ellipsoid
|
||||
var cartesian3 = new Cesium.Cartesian3(
|
||||
cartesian.x,
|
||||
cartesian.y,
|
||||
cartesian.z
|
||||
)
|
||||
var cartographic = ellipsoid.cartesianToCartographic(cartesian3)
|
||||
var lat = Cesium.Math.toDegrees(cartographic.latitude)
|
||||
var lng = Cesium.Math.toDegrees(cartographic.longitude)
|
||||
var alt = cartographic.height < 0 ? 0 : cartographic.height
|
||||
return {
|
||||
lng: lng,
|
||||
lat: lat,
|
||||
alt: alt
|
||||
}
|
||||
}
|
||||
// 计算一个到另一个点的方向
|
||||
direction(pointA, pointB) {
|
||||
//向量AB
|
||||
const vector2 = Cesium.Cartesian3.subtract(
|
||||
pointA,
|
||||
pointB,
|
||||
new Cesium.Cartesian3()
|
||||
)
|
||||
//归一化
|
||||
const normal = Cesium.Cartesian3.normalize(vector2, new Cesium.Cartesian3())
|
||||
//旋转矩阵 rotationMatrixFromPositionVelocity源码中有,并未出现在cesiumAPI中
|
||||
const rotationMatrix3 = Cesium.Transforms.rotationMatrixFromPositionVelocity(
|
||||
pointA,
|
||||
normal,
|
||||
Cesium.Ellipsoid.WGS84
|
||||
)
|
||||
const modelMatrix4 = Cesium.Matrix4.fromRotationTranslation(
|
||||
rotationMatrix3,
|
||||
pointA
|
||||
)
|
||||
// 获取getHeadingPitchRoll
|
||||
let m1 = Cesium.Transforms.eastNorthUpToFixedFrame(
|
||||
Cesium.Matrix4.getTranslation(modelMatrix4, new Cesium.Cartesian3()),
|
||||
Cesium.Ellipsoid.WGS84,
|
||||
new Cesium.Matrix4()
|
||||
)
|
||||
// 矩阵相除
|
||||
let m3 = Cesium.Matrix4.multiply(
|
||||
Cesium.Matrix4.inverse(m1, new Cesium.Matrix4()),
|
||||
modelMatrix4,
|
||||
new Cesium.Matrix4()
|
||||
)
|
||||
// 得到旋转矩阵
|
||||
let mat3 = Cesium.Matrix4.getMatrix3(m3, new Cesium.Matrix3())
|
||||
// 计算四元数
|
||||
let q = Cesium.Quaternion.fromRotationMatrix(mat3)
|
||||
// 计算旋转角(弧度)
|
||||
let hpr = Cesium.HeadingPitchRoll.fromQuaternion(q)
|
||||
// hpr.pitch = hpr.pitch + 3.14 / 2 + 3.14;
|
||||
hpr.pitch = 90
|
||||
let orientation = Cesium.Transforms.headingPitchRollQuaternion(pointA, hpr)
|
||||
return { hpr, orientation }
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param {index} 索引
|
||||
*/
|
||||
// 删除航点
|
||||
delPosition(index) {
|
||||
this.options.positions.splice(index, 1)
|
||||
// this.options.positions = this.options.positions.filter((item, index) => index !== i);
|
||||
this.remove()
|
||||
this.create()
|
||||
}
|
||||
// 获取最新的positions
|
||||
getNewPositions() {
|
||||
let positions = []
|
||||
for (let i = 0; i < this.billordPointLineMaps.length; i++) {
|
||||
const element = this.billordPointLineMaps[i]
|
||||
let position = this.cartesian3Towgs84(
|
||||
element.billboardEntity.position.getValue()
|
||||
)
|
||||
positions.push(position)
|
||||
}
|
||||
return positions
|
||||
}
|
||||
// 删除
|
||||
remove() {
|
||||
this.billordPointLineMaps.forEach((item, i) => {
|
||||
item.remove()
|
||||
})
|
||||
if (this.frustum) {
|
||||
this.frustum.remove()
|
||||
}
|
||||
this.viewer.entities.remove(this.entity)
|
||||
this.billordPointLineMaps = []
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param {String} type
|
||||
* @param {Number} index
|
||||
* @param {Array} position
|
||||
*/
|
||||
// 新增航点 (before,after,end)
|
||||
addPoint(positions) {
|
||||
this.options.positions = positions
|
||||
this.remove()
|
||||
this.create()
|
||||
}
|
||||
// 根据选中的点更新视锥的位置
|
||||
updateFrustumPosition(index) {
|
||||
if (!this.billordPointLineMaps || this.billordPointLineMaps.length === 0)
|
||||
return
|
||||
if (this.frustum) {
|
||||
this.frustum.show = true
|
||||
}
|
||||
let current = this.billordPointLineMaps[
|
||||
index
|
||||
].billboardEntity.position.getValue()
|
||||
if (index !== 0) {
|
||||
let obj
|
||||
let after =
|
||||
index === this.billordPointLineMaps.length - 1
|
||||
? this.billordPointLineMaps[
|
||||
index - 1
|
||||
].billboardEntity.position.getValue() // 获取前一个位置
|
||||
: this.billordPointLineMaps[
|
||||
index + 1
|
||||
].billboardEntity.position.getValue() // 获取下一个位置
|
||||
obj = this.direction(
|
||||
index === this.billordPointLineMaps.length - 1 ? after : current,
|
||||
index === this.billordPointLineMaps.length - 1 ? current : after
|
||||
)
|
||||
let { hpr } = obj
|
||||
this.frustum.updateFrustumHPR(
|
||||
hpr.heading,
|
||||
Cesium.Math.toRadians(this.frustum.pitch),
|
||||
hpr.roll
|
||||
)
|
||||
} else {
|
||||
let obj
|
||||
let after = this.billordPointLineMaps[1].billboardEntity.position.getValue()
|
||||
obj = this.direction(current, after)
|
||||
let { hpr } = obj
|
||||
this.frustum.updateFrustumHPR(
|
||||
hpr.heading,
|
||||
Cesium.Math.toRadians(this.frustum.pitch),
|
||||
hpr.roll
|
||||
)
|
||||
}
|
||||
if (current) {
|
||||
this.frustum.updateFrustumPosition('update', current)
|
||||
}
|
||||
let position = this.cartesian3Towgs84(current)
|
||||
this.billordPointLineMaps.forEach(item => {
|
||||
item.billboardEntity.label.show = false // 先将所有元素的 label.show 设置为 false
|
||||
})
|
||||
const targetItem = this.billordPointLineMaps.find(
|
||||
item => item.billboardEntity.index == index + 1
|
||||
)
|
||||
if (targetItem) {
|
||||
targetItem.billboardEntity.label.show = true // 然后找到匹配的 index 设置为 true
|
||||
}
|
||||
return position
|
||||
}
|
||||
flyTo() {
|
||||
let positionArray = []
|
||||
for (let i = 0; i < this.options.positions.length; i++) {
|
||||
let a = Cesium.Cartesian3.fromDegrees(
|
||||
this.options.positions[i].lng,
|
||||
this.options.positions[i].lat,
|
||||
this.options.positions[i].alt + this.options.height
|
||||
)
|
||||
positionArray.push(a.x, a.y, a.z)
|
||||
}
|
||||
let BoundingSphere = Cesium.BoundingSphere.fromVertices(positionArray)
|
||||
this.viewer.camera.flyToBoundingSphere(BoundingSphere, {
|
||||
offset: {
|
||||
heading: Cesium.Math.toRadians(0.0),
|
||||
pitch: Cesium.Math.toRadians(-80.0),
|
||||
roll: Cesium.Math.toRadians(0.0)
|
||||
}
|
||||
})
|
||||
}
|
||||
//计算航线的长度
|
||||
countLength() {
|
||||
if (this.options.positions.length < 2) {
|
||||
return 0
|
||||
} else {
|
||||
let lineString = []
|
||||
this.options.positions.forEach(item => {
|
||||
lineString.push([item.lng, item.lat])
|
||||
})
|
||||
var line = turf.lineString(lineString)
|
||||
return (turf.length(line) * 1000).toFixed(2)
|
||||
}
|
||||
}
|
||||
//计算航线时间
|
||||
countTime() {
|
||||
let time = Math.floor(Number(this.countLength())) / this.options.speed
|
||||
let s = Math.floor(time % 60)
|
||||
let m = Math.floor(time / 60)
|
||||
let str = m + '分' + s + '秒'
|
||||
return str
|
||||
}
|
||||
}
|
||||
25
src/Obj/Analysis/CircleViewShed/_element.js
Normal file
25
src/Obj/Analysis/CircleViewShed/_element.js
Normal file
@ -0,0 +1,25 @@
|
||||
function html() {
|
||||
return `
|
||||
<span class="custom-divider"></span>
|
||||
<div class="div-item">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<span class="label">视点高度</span>
|
||||
<div class="input-number input-number-unit-1">
|
||||
<input class="input" type="number" title="" min="0" max="999999" step="0.1" @model="viewPointHeight">
|
||||
<span class="unit">m</span>
|
||||
<span class="arrow"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<span class="label">采样精度</span>
|
||||
<input class="input" type="number" title="" min="1" max="100" step="1" @model="precision">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
||||
export { html }
|
||||
512
src/Obj/Analysis/CircleViewShed/_index.js
Normal file
512
src/Obj/Analysis/CircleViewShed/_index.js
Normal file
@ -0,0 +1,512 @@
|
||||
/*
|
||||
* @Author: Wang jianLei
|
||||
* @Date: 2022-05-17 21:49:28
|
||||
* @Last Modified by: Wang JianLei
|
||||
* @Last Modified time: 2022-05-19 22:08:14
|
||||
*/
|
||||
|
||||
let ViewShed = function (sdk, canvasEleId) {
|
||||
if (!sdk.viewer) throw new Error("no viewer object!");
|
||||
alert(canvasEleId)
|
||||
let canvasEle = document.getElementById(canvasEleId);
|
||||
if (!canvasEle) throw new Error("the canvas element is not exist");
|
||||
this.canvasEle = canvasEle;
|
||||
this.viewer = sdk.viewer;
|
||||
this.handler = undefined;
|
||||
this.lightCamera;
|
||||
this.pyramid;
|
||||
this.frustumPrimitive;
|
||||
this.viewershedPolygon;
|
||||
};
|
||||
ViewShed.prototype = {
|
||||
/**
|
||||
* 初始化handler
|
||||
*/
|
||||
initHandler() {
|
||||
if (this.handler) {
|
||||
this.handler.destroy();
|
||||
this.handler = undefined;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 开始执行视域分析
|
||||
* @param {number} precision 精度,值越大创建耗时越长,建议在10~20之间
|
||||
*/
|
||||
createViewshed: function (precision) {
|
||||
let $this = this;
|
||||
let scene = $this.viewer.scene;
|
||||
$this.initHandler();
|
||||
$this.clearAll();
|
||||
$this.handler = new Cesium.ScreenSpaceEventHandler($this.viewer.canvas);
|
||||
$this.handler.setInputAction((event) => {
|
||||
// 禁止地球旋转和缩放,地球的旋转会对鼠标移动监听有影响,所以需要禁止
|
||||
scene.screenSpaceCameraController.enableRotate = false;
|
||||
scene.screenSpaceCameraController.enableZoom = false;
|
||||
scene.globe.depthTestAgainstTerrain = true;
|
||||
let earthPosition = scene.pickPosition(event.position);
|
||||
let pos = $this.cartesian3ToDegree(earthPosition);
|
||||
$this.handler.setInputAction(function (event) {
|
||||
let newPosition = scene.pickPosition(event.endPosition);
|
||||
if (Cesium.defined(newPosition)) {
|
||||
let pos1 = $this.cartesian3ToDegree(newPosition);
|
||||
let distance = Cesium.Cartesian3.distance(newPosition, earthPosition);
|
||||
let angle = $this.getAngle(pos[0], pos[1], pos1[0], pos1[1]);
|
||||
let pitch = $this.getPitch(earthPosition, newPosition);
|
||||
$this.ViewShedOptions = {
|
||||
viewPosition: earthPosition, //观测点 笛卡尔坐标
|
||||
endPosition: newPosition, //目标点 笛卡尔坐标
|
||||
direction: angle, //观测方位角 默认为`0`,范围`0~360`
|
||||
pitch: pitch, //俯仰角,radius,默认为`0`
|
||||
horizontalViewAngle: 90, //可视域水平夹角,默认为 `90`,范围`0~360`
|
||||
verticalViewAngle: 60, //可视域垂直夹角,默认为`60`,范围`0~180`
|
||||
visibleAreaColor: Cesium.Color.GREEN, //可视区域颜色,默认为`green`
|
||||
invisibleAreaColor: Cesium.Color.RED, //不可见区域颜色,默认为`red`
|
||||
visualRange: distance, //距离,单位`米`
|
||||
};
|
||||
$this.updateViewShed();
|
||||
}
|
||||
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
|
||||
}, Cesium.ScreenSpaceEventType.LEFT_DOWN);
|
||||
|
||||
$this.handler.setInputAction(() => {
|
||||
$this.initHandler();
|
||||
// 开启地球旋转和缩放
|
||||
scene.screenSpaceCameraController.enableRotate = true;
|
||||
scene.screenSpaceCameraController.enableZoom = true;
|
||||
$this.drawViewershed(precision);
|
||||
}, Cesium.ScreenSpaceEventType.LEFT_UP);
|
||||
},
|
||||
|
||||
ReturnDistance(pos0, pos1) {
|
||||
let distance = 0;
|
||||
let point1cartographic = Cesium.Cartographic.fromCartesian(pos0);
|
||||
let point2cartographic = Cesium.Cartographic.fromCartesian(pos1);
|
||||
/**根据经纬度计算出距离**/
|
||||
let geodesic = new Cesium.EllipsoidGeodesic();
|
||||
geodesic.setEndPoints(point1cartographic, point2cartographic);
|
||||
let s = geodesic.surfaceDistance;
|
||||
return s;
|
||||
},
|
||||
getHeight(x, y, objectsToExclude) {
|
||||
let endCartographic = Cesium.Cartographic.fromDegrees(x, y);
|
||||
let endHeight = this.viewer.scene.sampleHeight(
|
||||
endCartographic,
|
||||
objectsToExclude
|
||||
);
|
||||
return endHeight;
|
||||
},
|
||||
|
||||
cartesian3ToDegree: function (Cartesian3) {
|
||||
let _ellipsoid = this.viewer.scene.globe.ellipsoid;
|
||||
let _cartographic = _ellipsoid.cartesianToCartographic(Cartesian3);
|
||||
let _lat = Cesium.Math.toDegrees(_cartographic.latitude);
|
||||
let _lng = Cesium.Math.toDegrees(_cartographic.longitude);
|
||||
let _alt = _cartographic.height;
|
||||
return [_lng, _lat, _alt];
|
||||
},
|
||||
getAngle: function (lng1, lat1, lng2, lat2) {
|
||||
let dRotateAngle = Math.atan2(Math.abs(lng1 - lng2), Math.abs(lat1 - lat2));
|
||||
if (lng2 >= lng1) {
|
||||
dRotateAngle = lat2 < lat1 ? Math.PI - dRotateAngle : dRotateAngle;
|
||||
} else {
|
||||
dRotateAngle =
|
||||
lat2 >= lat1 ? 2 * Math.PI - dRotateAngle : Math.PI + dRotateAngle;
|
||||
}
|
||||
dRotateAngle = (dRotateAngle * 180) / Math.PI;
|
||||
return dRotateAngle;
|
||||
},
|
||||
|
||||
getPitch(pointA, pointB) {
|
||||
let transfrom = Cesium.Transforms.eastNorthUpToFixedFrame(pointA);
|
||||
const vector = Cesium.Cartesian3.subtract(
|
||||
pointB,
|
||||
pointA,
|
||||
new Cesium.Cartesian3()
|
||||
);
|
||||
let direction = Cesium.Matrix4.multiplyByPointAsVector(
|
||||
Cesium.Matrix4.inverse(transfrom, transfrom),
|
||||
vector,
|
||||
vector
|
||||
);
|
||||
Cesium.Cartesian3.normalize(direction, direction);
|
||||
return Cesium.Math.PI_OVER_TWO - Cesium.Math.acosClamped(direction.z);
|
||||
},
|
||||
|
||||
updateViewShed: function () {
|
||||
this.clear();
|
||||
this.setLightCamera();
|
||||
this.addVisualPyramid();
|
||||
this.createFrustum();
|
||||
},
|
||||
clear: function () {
|
||||
if (this.pyramid) {
|
||||
this.viewer.entities.removeById(this.pyramid.id);
|
||||
this.pyramid = undefined;
|
||||
}
|
||||
if (this.frustumPrimitive) {
|
||||
this.viewer.scene.primitives.remove(this.frustumPrimitive);
|
||||
this.frustumPrimitive = undefined;
|
||||
}
|
||||
if (this.debugModelMatrixPrimitive) {
|
||||
this.viewer.scene.primitives.remove(this.debugModelMatrixPrimitive);
|
||||
this.debugModelMatrixPrimitive = undefined;
|
||||
}
|
||||
},
|
||||
clearAll: function () {
|
||||
this.clear();
|
||||
if (this.viewershedPolygon) {
|
||||
this.viewer.scene.primitives.remove(this.viewershedPolygon);
|
||||
this.viewershedPolygon = undefined;
|
||||
}
|
||||
},
|
||||
addVisualPyramid: function () {
|
||||
let options = this.ViewShedOptions;
|
||||
let position = options.viewPosition;
|
||||
let visualRange = Number(options.visualRange);
|
||||
let transform = Cesium.Transforms.eastNorthUpToFixedFrame(position);
|
||||
this.debugModelMatrixPrimitive = this.viewer.scene.primitives.add(
|
||||
new Cesium.DebugModelMatrixPrimitive({
|
||||
modelMatrix: transform,
|
||||
length: 5.0,
|
||||
})
|
||||
);
|
||||
const halfClock = options.horizontalViewAngle / 2;
|
||||
const halfCone = options.verticalViewAngle / 2;
|
||||
const pitch = Cesium.Math.toDegrees(options.pitch);
|
||||
const ellipsoid = new Cesium.EllipsoidGraphics({
|
||||
radii: new Cesium.Cartesian3(visualRange, visualRange, visualRange),
|
||||
minimumClock: Cesium.Math.toRadians(90 - options.direction - halfClock),
|
||||
maximumClock: Cesium.Math.toRadians(90 - options.direction + halfClock),
|
||||
minimumCone: Cesium.Math.toRadians(90 - pitch - halfCone),
|
||||
maximumCone: Cesium.Math.toRadians(90 - pitch + halfCone),
|
||||
fill: false,
|
||||
outline: true,
|
||||
subdivisions: 256,
|
||||
stackPartitions: 64,
|
||||
slicePartitions: 64,
|
||||
outlineColor: Cesium.Color.YELLOWGREEN.withAlpha(0.5),
|
||||
});
|
||||
const pyramidEntity = new Cesium.Entity({
|
||||
position: position,
|
||||
ellipsoid,
|
||||
});
|
||||
this.pyramid = this.viewer.entities.add(pyramidEntity);
|
||||
},
|
||||
setLightCamera: function () {
|
||||
if (!this.lightCamera) {
|
||||
this.lightCamera = new Cesium.Camera(this.viewer.scene);
|
||||
}
|
||||
let options = this.ViewShedOptions;
|
||||
let visualRange = Number(options.visualRange);
|
||||
this.lightCamera.position = options.viewPosition;
|
||||
this.lightCamera.frustum.near = 0.1;
|
||||
this.lightCamera.frustum.far = visualRange;
|
||||
const hr = Cesium.Math.toRadians(options.horizontalViewAngle);
|
||||
const vr = Cesium.Math.toRadians(options.verticalViewAngle);
|
||||
this.lightCamera.frustum.aspectRatio =
|
||||
(visualRange * Math.tan(hr / 2) * 2) /
|
||||
(visualRange * Math.tan(vr / 2) * 2);
|
||||
this.lightCamera.frustum.fov = hr > vr ? hr : vr;
|
||||
this.lightCamera.setView({
|
||||
destination: options.viewPosition,
|
||||
orientation: {
|
||||
heading: Cesium.Math.toRadians(options.direction || 0),
|
||||
pitch: options.pitch || 0,
|
||||
roll: 0,
|
||||
},
|
||||
});
|
||||
},
|
||||
createFrustum: function () {
|
||||
const scratchRight = new Cesium.Cartesian3();
|
||||
const scratchRotation = new Cesium.Matrix3();
|
||||
const scratchOrientation = new Cesium.Quaternion();
|
||||
const direction = this.lightCamera.directionWC;
|
||||
const up = this.lightCamera.upWC;
|
||||
let right = this.lightCamera.rightWC;
|
||||
right = Cesium.Cartesian3.negate(right, scratchRight);
|
||||
let rotation = scratchRotation;
|
||||
Cesium.Matrix3.setColumn(rotation, 0, right, rotation);
|
||||
Cesium.Matrix3.setColumn(rotation, 1, up, rotation);
|
||||
Cesium.Matrix3.setColumn(rotation, 2, direction, rotation);
|
||||
let orientation = Cesium.Quaternion.fromRotationMatrix(
|
||||
rotation,
|
||||
scratchOrientation
|
||||
);
|
||||
let instanceOutline = new Cesium.GeometryInstance({
|
||||
geometry: new Cesium.FrustumOutlineGeometry({
|
||||
frustum: this.lightCamera.frustum,
|
||||
origin: this.ViewShedOptions.viewPosition,
|
||||
orientation: orientation,
|
||||
}),
|
||||
id: "视椎体轮廓线" + Math.random().toString(36).substr(2),
|
||||
attributes: {
|
||||
color: Cesium.ColorGeometryInstanceAttribute.fromColor(
|
||||
new Cesium.Color(0.0, 1.0, 0.0, 1.0)
|
||||
),
|
||||
show: new Cesium.ShowGeometryInstanceAttribute(true),
|
||||
},
|
||||
});
|
||||
this.frustumPrimitive = this.viewer.scene.primitives.add(
|
||||
new Cesium.Primitive({
|
||||
geometryInstances: instanceOutline,
|
||||
appearance: new Cesium.PerInstanceColorAppearance({
|
||||
flat: true,
|
||||
translucent: false,
|
||||
closed: true,
|
||||
}),
|
||||
})
|
||||
);
|
||||
},
|
||||
createPoint: function (firstPos, secondPos) {
|
||||
let entity4FirstPos = new Cesium.Entity({
|
||||
name: "firstPos",
|
||||
show: true,
|
||||
position: firstPos,
|
||||
point: {
|
||||
show: true,
|
||||
pixelSize: 20,
|
||||
color: Cesium.Color.RED,
|
||||
outlineColor: Cesium.Color.YELLOW,
|
||||
outlineWidth: 5,
|
||||
},
|
||||
description: `
|
||||
<p>这是绘制的视椎体起点</p>`,
|
||||
});
|
||||
this.viewer.entities.add(entity4FirstPos);
|
||||
let entity4SecondPos = new Cesium.Entity({
|
||||
name: "secondPos",
|
||||
show: true,
|
||||
position: secondPos,
|
||||
point: {
|
||||
show: true,
|
||||
pixelSize: 30,
|
||||
color: Cesium.Color.YELLOW,
|
||||
outlineColor: Cesium.Color.RED,
|
||||
outlineWidth: 8,
|
||||
},
|
||||
description: `
|
||||
<p>这是绘制的视椎体视角终点</p>`,
|
||||
});
|
||||
this.viewer.entities.add(entity4SecondPos);
|
||||
},
|
||||
|
||||
//绘制可视域
|
||||
add(positionArr) {
|
||||
let polygon = new Cesium.PolygonGeometry({
|
||||
polygonHierarchy: new Cesium.PolygonHierarchy(
|
||||
Cesium.Cartesian3.fromDegreesArray(positionArr)
|
||||
),
|
||||
height: 0.0,
|
||||
extrudedHeight: 0.0,
|
||||
vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT,
|
||||
stRotation: 0.0, // 纹理的旋转坐标(以弧度为单位),正旋转是逆时针方向
|
||||
ellipsoid: Cesium.Ellipsoid.WGS84,
|
||||
granularity: Cesium.Math.RADIANS_PER_DEGREE, // 每个纬度和经度之间的距离(以弧度为单位),确定缓冲区中的位置数
|
||||
perPositionHeight: false, // 每个位置点使用的高度
|
||||
closeTop: true,
|
||||
closeBottom: true,
|
||||
// NONE 与椭圆表面不符的直线;GEODESIC 遵循测地路径;RHUMB 遵循大黄蜂或恶魔般的道路。
|
||||
arcType: Cesium.ArcType.GEODESIC, // 多边形边缘线型
|
||||
});
|
||||
|
||||
let polygonInstance = new Cesium.GeometryInstance({
|
||||
geometry: polygon,
|
||||
name: "ViewershedPolygon",
|
||||
attributes: {
|
||||
color: Cesium.ColorGeometryInstanceAttribute.fromColor(
|
||||
Cesium.Color.BLUE.withAlpha(0.6)
|
||||
),
|
||||
show: new Cesium.ShowGeometryInstanceAttribute(true), //显示或者隐藏
|
||||
},
|
||||
});
|
||||
this.viewershedPolygon = this.viewer.scene.primitives.add(
|
||||
new Cesium.GroundPrimitive({
|
||||
geometryInstances: polygonInstance,
|
||||
appearance: new Cesium.EllipsoidSurfaceAppearance({
|
||||
aboveGround: true,
|
||||
material: new Cesium.Material({
|
||||
fabric: {
|
||||
type: "Image",
|
||||
uniforms: {
|
||||
image: this.returnImgae(),
|
||||
},
|
||||
},
|
||||
}),
|
||||
}),
|
||||
})
|
||||
);
|
||||
},
|
||||
drawViewershed(precision) {
|
||||
const pos = this.cartesian3ToDegree(this.ViewShedOptions.viewPosition);
|
||||
const radius = this.ViewShedOptions.visualRange;
|
||||
const direction = this.ViewShedOptions.direction;
|
||||
let boundary = this.computeBoundaryOptions(pos, radius, direction);
|
||||
const bbox = boundary.bbox;
|
||||
let mask = turf.polygon([boundary.boundaryPoints]);
|
||||
const dis = this.ViewShedOptions.visualRange / (precision * 1000);
|
||||
let gridPoints = turf.pointGrid(bbox, dis, { mask: mask });
|
||||
|
||||
let pointsResult = this.createTargetPoints(gridPoints, dis, pos);
|
||||
let variogram = kriging.train(
|
||||
pointsResult.values,
|
||||
pointsResult.lngs,
|
||||
pointsResult.lats,
|
||||
"exponential",
|
||||
0,
|
||||
100
|
||||
);
|
||||
let grid = kriging.grid([boundary.boundaryPoints], variogram, dis / 1000);
|
||||
const colors = [
|
||||
"#ff000080",
|
||||
"#ff000080",
|
||||
"#ff000080",
|
||||
"#ff000080",
|
||||
"#ff000080",
|
||||
"#ff000080",
|
||||
"#00ff0080",
|
||||
"#00ff0080",
|
||||
"#00ff0080",
|
||||
"#00ff0080",
|
||||
"#00ff0080",
|
||||
"#00ff0080",
|
||||
];
|
||||
|
||||
this.canvasEle.width = 3840;
|
||||
this.canvasEle.height = 2160;
|
||||
kriging.plot(
|
||||
this.canvasEle,
|
||||
grid,
|
||||
[bbox[0], bbox[2]],
|
||||
[bbox[1], bbox[3]],
|
||||
colors
|
||||
);
|
||||
this.add(boundary.positionArr);
|
||||
},
|
||||
computeBoundaryOptions(pos, radius, angle) {
|
||||
let Ea = 6378137; // 赤道半径
|
||||
let Eb = 6356725; // 极半径
|
||||
const lng = pos[0],
|
||||
lat = pos[1];
|
||||
const bbox = [lng, lat, lng, lat]; //[minX, minY, maxX, maxY]
|
||||
let positionArr = [];
|
||||
let boundaryPoints = [];
|
||||
positionArr.push(lng, lat);
|
||||
boundaryPoints.push([lng, lat]);
|
||||
//正北是0°
|
||||
let start = angle + 45 > 360 ? angle - 45 - 360 : angle - 45;
|
||||
let end = start + 90;
|
||||
for (let i = start; i <= end; i++) {
|
||||
let dx = radius * Math.sin((i * Math.PI) / 180.0);
|
||||
let dy = radius * Math.cos((i * Math.PI) / 180.0);
|
||||
let ec = Eb + ((Ea - Eb) * (90.0 - lat)) / 90.0;
|
||||
let ed = ec * Math.cos((lat * Math.PI) / 180);
|
||||
let BJD = lng + ((dx / ed) * 180.0) / Math.PI;
|
||||
let BWD = lat + ((dy / ec) * 180.0) / Math.PI;
|
||||
positionArr.push(BJD, BWD);
|
||||
boundaryPoints.push([BJD, BWD]);
|
||||
this.refreshBBox(bbox, BJD, BWD);
|
||||
}
|
||||
boundaryPoints.push([lng, lat]);
|
||||
return {
|
||||
positionArr,
|
||||
boundaryPoints,
|
||||
bbox,
|
||||
};
|
||||
},
|
||||
/**
|
||||
* 更新外围矩形 Bbox
|
||||
* @param {Array} result 外围矩形Bbox-[minX, minY, maxX, maxY]
|
||||
* @param {Number} x 经度
|
||||
* @param {Number} y 纬度
|
||||
*/
|
||||
refreshBBox(result, x, y) {
|
||||
result[0] = x < result[0] ? x : result[0];
|
||||
result[1] = y < result[1] ? y : result[1];
|
||||
result[2] = x > result[2] ? x : result[2];
|
||||
result[3] = y > result[3] ? y : result[3];
|
||||
},
|
||||
/**
|
||||
* 插值点用射线判断通视性
|
||||
* @param {*} gridPoints 网格点
|
||||
* @param {*} step 步长,可以理解成是精度
|
||||
* @param {*} sourcePos 视域分析起点
|
||||
* @returns kriging插值所需的参数对象{ values:[], lngs:[], lats:[]}
|
||||
*/
|
||||
createTargetPoints(gridPoints, step, sourcePos) {
|
||||
let positionArr = [];
|
||||
let objectsToExclude = [
|
||||
this.frustumPrimitive,
|
||||
this.pyramid,
|
||||
this.debugModelMatrixPrimitive,
|
||||
];
|
||||
let values = [],
|
||||
lngs = [],
|
||||
lats = [];
|
||||
let height = this.getHeight(sourcePos[0], sourcePos[1], objectsToExclude);
|
||||
positionArr.push({
|
||||
x: sourcePos[0],
|
||||
y: sourcePos[1],
|
||||
z: height,
|
||||
});
|
||||
let viewPoint = this.ViewShedOptions.viewPosition;
|
||||
for (let index = 0; index < gridPoints.features.length; index++) {
|
||||
const feature = gridPoints.features[index];
|
||||
const coords = feature.geometry.coordinates;
|
||||
const x = coords[0],
|
||||
y = coords[1];
|
||||
let h = this.getHeight(x, y, objectsToExclude);
|
||||
let endPoint = Cesium.Cartesian3.fromDegrees(x, y, h);
|
||||
let direction = Cesium.Cartesian3.normalize(
|
||||
Cesium.Cartesian3.subtract(
|
||||
endPoint,
|
||||
viewPoint,
|
||||
new Cesium.Cartesian3()
|
||||
),
|
||||
new Cesium.Cartesian3()
|
||||
);
|
||||
// 建立射线
|
||||
let ray = new Cesium.Ray(viewPoint, direction);
|
||||
let result = this.viewer.scene.pickFromRay(ray, objectsToExclude); // 计算交互点,返回第一个
|
||||
if (result) {
|
||||
let buffer = this.ReturnDistance(endPoint, result.position);
|
||||
// let M_color = Cesium.Color.GREEN;
|
||||
if (buffer > step) {
|
||||
// M_color = Cesium.Color.RED;
|
||||
values.push(0);
|
||||
} else {
|
||||
values.push(1);
|
||||
}
|
||||
lngs.push(x);
|
||||
lats.push(y);
|
||||
// this.viewer.entities.add(
|
||||
// new Cesium.Entity({
|
||||
// name: "插值点哦",
|
||||
// show: true,
|
||||
// position: endPoint,
|
||||
// point: {
|
||||
// show: true,
|
||||
// pixelSize: 10,
|
||||
// color: M_color,
|
||||
// outlineWidth: 2,
|
||||
// outlineColor: Cesium.Color.YELLOW,
|
||||
// },
|
||||
// })
|
||||
// );
|
||||
}
|
||||
}
|
||||
return {
|
||||
values,
|
||||
lngs,
|
||||
lats,
|
||||
};
|
||||
},
|
||||
/**
|
||||
* canvas转image图片
|
||||
* @returns base64图片
|
||||
*/
|
||||
returnImgae() {
|
||||
return this.canvasEle.toDataURL("image/png");
|
||||
},
|
||||
};
|
||||
|
||||
export default ViewShed;
|
||||
131
src/Obj/Analysis/CircleViewShed/glsl.js
Normal file
131
src/Obj/Analysis/CircleViewShed/glsl.js
Normal file
@ -0,0 +1,131 @@
|
||||
export default `
|
||||
#define USE_CUBE_MAP_SHADOW true
|
||||
uniform sampler2D colorTexture;
|
||||
uniform sampler2D depthTexture;
|
||||
varying vec2 v_textureCoordinates;
|
||||
uniform mat4 camera_projection_matrix;
|
||||
uniform mat4 camera_view_matrix;
|
||||
uniform samplerCube shadowMap_textureCube;
|
||||
uniform mat4 shadowMap_matrix;
|
||||
uniform vec4 shadowMap_lightPositionEC;
|
||||
uniform vec4 shadowMap_normalOffsetScaleDistanceMaxDistanceAndDarkness;
|
||||
uniform vec4 shadowMap_texelSizeDepthBiasAndNormalShadingSmooth;
|
||||
uniform float helsing_viewDistance;
|
||||
uniform vec4 helsing_visibleAreaColor;
|
||||
uniform vec4 helsing_invisibleAreaColor;
|
||||
|
||||
struct zx_shadowParameters
|
||||
{
|
||||
vec3 texCoords;
|
||||
float depthBias;
|
||||
float depth;
|
||||
float nDotL;
|
||||
vec2 texelStepSize;
|
||||
float normalShadingSmooth;
|
||||
float darkness;
|
||||
};
|
||||
|
||||
float czm_shadowVisibility(samplerCube shadowMap, zx_shadowParameters shadowParameters)
|
||||
{
|
||||
float depthBias = shadowParameters.depthBias;
|
||||
float depth = shadowParameters.depth;
|
||||
float nDotL = shadowParameters.nDotL;
|
||||
float normalShadingSmooth = shadowParameters.normalShadingSmooth;
|
||||
float darkness = shadowParameters.darkness;
|
||||
vec3 uvw = shadowParameters.texCoords;
|
||||
depth -= depthBias;
|
||||
float visibility = czm_shadowDepthCompare(shadowMap, uvw, depth);
|
||||
return czm_private_shadowVisibility(visibility, nDotL, normalShadingSmooth, darkness);
|
||||
}
|
||||
|
||||
vec4 getPositionEC(){
|
||||
return czm_windowToEyeCoordinates(gl_FragCoord);
|
||||
}
|
||||
|
||||
vec3 getNormalEC(){
|
||||
return vec3(1.);
|
||||
}
|
||||
|
||||
vec4 toEye(in vec2 uv,in float depth){
|
||||
vec2 xy=vec2((uv.x*2.-1.),(uv.y*2.-1.));
|
||||
vec4 posInCamera=czm_inverseProjection*vec4(xy,depth,1.);
|
||||
posInCamera=posInCamera/posInCamera.w;
|
||||
return posInCamera;
|
||||
}
|
||||
|
||||
vec3 pointProjectOnPlane(in vec3 planeNormal,in vec3 planeOrigin,in vec3 point){
|
||||
vec3 v01=point-planeOrigin;
|
||||
float d=dot(planeNormal,v01);
|
||||
return(point-planeNormal*d);
|
||||
}
|
||||
|
||||
float getDepth(in vec4 depth){
|
||||
float z_window=czm_unpackDepth(depth);
|
||||
z_window=czm_reverseLogDepth(z_window);
|
||||
float n_range=czm_depthRange.near;
|
||||
float f_range=czm_depthRange.far;
|
||||
return(2.*z_window-n_range-f_range)/(f_range-n_range);
|
||||
}
|
||||
|
||||
float shadow(in vec4 positionEC){
|
||||
vec3 normalEC=getNormalEC();
|
||||
zx_shadowParameters shadowParameters;
|
||||
shadowParameters.texelStepSize=shadowMap_texelSizeDepthBiasAndNormalShadingSmooth.xy;
|
||||
shadowParameters.depthBias=shadowMap_texelSizeDepthBiasAndNormalShadingSmooth.z;
|
||||
shadowParameters.normalShadingSmooth=shadowMap_texelSizeDepthBiasAndNormalShadingSmooth.w;
|
||||
shadowParameters.darkness=shadowMap_normalOffsetScaleDistanceMaxDistanceAndDarkness.w;
|
||||
vec3 directionEC=positionEC.xyz-shadowMap_lightPositionEC.xyz;
|
||||
float distance=length(directionEC);
|
||||
directionEC=normalize(directionEC);
|
||||
float radius=shadowMap_lightPositionEC.w;
|
||||
if(distance>radius)
|
||||
{
|
||||
return 2.0;
|
||||
}
|
||||
vec3 directionWC=czm_inverseViewRotation*directionEC;
|
||||
shadowParameters.depth=distance/radius-0.0003;
|
||||
shadowParameters.nDotL=clamp(dot(normalEC,-directionEC),0.,1.);
|
||||
shadowParameters.texCoords=directionWC;
|
||||
float visibility=czm_shadowVisibility(shadowMap_textureCube,shadowParameters);
|
||||
return visibility;
|
||||
}
|
||||
|
||||
bool visible(in vec4 result)
|
||||
{
|
||||
result.x/=result.w;
|
||||
result.y/=result.w;
|
||||
result.z/=result.w;
|
||||
return result.x>=-1.&&result.x<=1.
|
||||
&&result.y>=-1.&&result.y<=1.
|
||||
&&result.z>=-1.&&result.z<=1.;
|
||||
}
|
||||
|
||||
void main(){
|
||||
// 釉色 = 结构二维(颜色纹理, 纹理坐标)
|
||||
gl_FragColor = texture2D(colorTexture, v_textureCoordinates);
|
||||
// 深度 = 获取深度(结构二维(深度纹理, 纹理坐标))
|
||||
float depth = getDepth(texture2D(depthTexture, v_textureCoordinates));
|
||||
// 视角 = (纹理坐标, 深度)
|
||||
vec4 viewPos = toEye(v_textureCoordinates, depth);
|
||||
// 世界坐标
|
||||
vec4 wordPos = czm_inverseView * viewPos;
|
||||
// 虚拟相机中坐标
|
||||
vec4 vcPos = camera_view_matrix * wordPos;
|
||||
float near = .001 * helsing_viewDistance;
|
||||
float dis = length(vcPos.xyz);
|
||||
if(dis > near && dis < helsing_viewDistance){
|
||||
// 透视投影
|
||||
vec4 posInEye = camera_projection_matrix * vcPos;
|
||||
// 可视区颜色
|
||||
// vec4 helsing_visibleAreaColor=vec4(0.,1.,0.,.5);
|
||||
// vec4 helsing_invisibleAreaColor=vec4(1.,0.,0.,.5);
|
||||
if(visible(posInEye)){
|
||||
float vis = shadow(viewPos);
|
||||
if(vis > 0.3){
|
||||
// gl_FragColor = mix(gl_FragColor,helsing_visibleAreaColor,.5);
|
||||
} else {
|
||||
gl_FragColor = mix(gl_FragColor,helsing_invisibleAreaColor,.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
}`;
|
||||
380
src/Obj/Analysis/CircleViewShed/index.js
Normal file
380
src/Obj/Analysis/CircleViewShed/index.js
Normal file
@ -0,0 +1,380 @@
|
||||
// ViewShed.js
|
||||
import Event from '../../../Event'
|
||||
import MouseTip from '../../../MouseTip'
|
||||
import Tools from '../../../Tools'
|
||||
import EventBinding from '../../Element/Dialog/eventBinding'
|
||||
import Dialog from '../../../BaseDialog'
|
||||
import { html } from './_element'
|
||||
/**
|
||||
* @constructor
|
||||
* @description 可视域分析
|
||||
* @param sdk
|
||||
* @param {Object} options 选项。
|
||||
* @param {Number} options.viewPointHeight=1.8 视点高度(m)。
|
||||
* @param {Number} options.precision=20 精度。
|
||||
* @param {String} options.visibleAreaColor=#008000 可视区域颜色。
|
||||
* @param {String} options.invisibleAreaColor=#FF0000 不可视区域颜色。
|
||||
*/
|
||||
class CircleViewShed extends Tools {
|
||||
#intervalEvents = new Map()
|
||||
|
||||
constructor(sdk, options = {}, _Dialog = {}) {
|
||||
super(sdk, options)
|
||||
|
||||
this.viewer = sdk.viewer
|
||||
this.options = {}
|
||||
this.options.visibleAreaColor = options.visibleAreaColor || '#008000'
|
||||
this.options.invisibleAreaColor = options.invisibleAreaColor || '#FF0000'
|
||||
this.ids = []
|
||||
this.primitives = []
|
||||
this.viewpointPrimitive = null
|
||||
|
||||
this._elms = {}
|
||||
this.precision = options.precision
|
||||
this.viewPointHeight = options.viewPointHeight
|
||||
this.Dialog = _Dialog
|
||||
this._EventBinding = new EventBinding()
|
||||
this.html = null
|
||||
YJ.Analysis.Analyses.push(this)
|
||||
CircleViewShed.edit(this)
|
||||
// CircleViewShed.create(this)
|
||||
}
|
||||
|
||||
get viewPointHeight() {
|
||||
return this.options.viewPointHeight
|
||||
}
|
||||
|
||||
set viewPointHeight(v) {
|
||||
let viewPointHeight = Math.floor(Number(v) * 10) / 10
|
||||
if (isNaN(viewPointHeight)) {
|
||||
viewPointHeight = 1.8
|
||||
}
|
||||
if (viewPointHeight < 0) {
|
||||
viewPointHeight = 0
|
||||
}
|
||||
this.options.viewPointHeight = viewPointHeight
|
||||
this._elms.viewPointHeight &&
|
||||
this._elms.viewPointHeight.forEach(item => {
|
||||
item.value = viewPointHeight
|
||||
})
|
||||
}
|
||||
|
||||
get precision() {
|
||||
return this.options.precision
|
||||
}
|
||||
|
||||
set precision(v) {
|
||||
let precision = Math.floor(Number(v))
|
||||
if (isNaN(precision)) {
|
||||
precision = 20
|
||||
} else if (precision < 1) {
|
||||
precision = 1
|
||||
}
|
||||
this.options.precision = precision
|
||||
this._elms.precision &&
|
||||
this._elms.precision.forEach(item => {
|
||||
item.value = precision
|
||||
})
|
||||
}
|
||||
|
||||
static create(that) {
|
||||
let count = 0
|
||||
if (!YJ.Measure.GetMeasureStatus()) {
|
||||
if (that._DialogObject && that._DialogObject.close) {
|
||||
that._DialogObject.close()
|
||||
that._DialogObject = null
|
||||
}
|
||||
let Draw = new YJ.Draw.DrawCircle(that.sdk)
|
||||
Draw.start(async (a, options) => {
|
||||
// that.center = options.center
|
||||
if(!options) {
|
||||
return
|
||||
}
|
||||
that.radius = options.radius
|
||||
let positions = await Cesium.sampleTerrainMostDetailed(
|
||||
that.sdk.viewer.terrainProvider,
|
||||
[Cesium.Cartographic.fromDegrees(options.center.lng, options.center.lat)]
|
||||
);
|
||||
that.center = {
|
||||
lng: options.center.lng,
|
||||
lat: options.center.lat,
|
||||
alt: positions[0].height
|
||||
}
|
||||
await that.analyse()
|
||||
})
|
||||
} else {
|
||||
console.log('上一次测量未结束')
|
||||
}
|
||||
}
|
||||
|
||||
static async edit(that) {
|
||||
if (that._DialogObject && that._DialogObject.close) {
|
||||
that._DialogObject.close()
|
||||
that._DialogObject = null
|
||||
}
|
||||
that._DialogObject = await new Dialog(that.sdk.viewer._container, {
|
||||
title: '圆形视域分析',
|
||||
left: '180px',
|
||||
top: '100px',
|
||||
closeCallBack: () => {
|
||||
that.Dialog.closeCallBack && that.Dialog.closeCallBack()
|
||||
YJ.Measure.SetMeasureStatus(false)
|
||||
}
|
||||
})
|
||||
await that._DialogObject.init()
|
||||
that._DialogObject._element.body.className =
|
||||
that._DialogObject._element.body.className + ' circle-view-shed'
|
||||
let contentElm = document.createElement('div')
|
||||
contentElm.innerHTML = html()
|
||||
that._DialogObject.contentAppChild(contentElm)
|
||||
|
||||
let drawElm = document.createElement('button')
|
||||
drawElm.innerHTML = '绘制'
|
||||
drawElm.addEventListener('click', () => {
|
||||
let terrainAvailability = that.viewer.terrainProvider.availability;
|
||||
if (!terrainAvailability) {
|
||||
window.ELEMENT && window.ELEMENT.Message({
|
||||
message: '未加载地形数据!',
|
||||
type: 'warning',
|
||||
duration: 1500
|
||||
});
|
||||
return
|
||||
}
|
||||
CircleViewShed.create(that)
|
||||
})
|
||||
that._DialogObject.footAppChild(drawElm)
|
||||
|
||||
let all_elm = contentElm.getElementsByTagName('*')
|
||||
that._EventBinding.on(that, all_elm)
|
||||
that._elms = that._EventBinding.element
|
||||
}
|
||||
|
||||
analyse() {
|
||||
// this.destroy()
|
||||
let center = [this.center.lng, this.center.lat]
|
||||
let radius = this.radius / 1000
|
||||
let circle = turf.circle(center, radius, {
|
||||
steps: 180,
|
||||
units: 'kilometers',
|
||||
properties: { foo: 'bar' }
|
||||
})
|
||||
if (!this.viewpointPrimitive) {
|
||||
this.viewpointPrimitive = this.viewer.scene.primitives.add(
|
||||
new Cesium.PointPrimitiveCollection()
|
||||
)
|
||||
}
|
||||
if (!this.viewBillboardPrimitive) {
|
||||
this.viewBillboardPrimitive = this.viewer.scene.primitives.add(
|
||||
new Cesium.BillboardCollection()
|
||||
)
|
||||
}
|
||||
|
||||
let array = []
|
||||
let distance = radius / this.precision
|
||||
for (let i = 1; i < circle.geometry.coordinates[0].length; i++) {
|
||||
let line = turf.lineString([center, circle.geometry.coordinates[0][i]])
|
||||
let array2 = []
|
||||
for (let j = 1; j <= this.precision; j++) {
|
||||
let sliced = turf.lineSliceAlong(line, 0, distance * j, {
|
||||
units: 'kilometers'
|
||||
})
|
||||
array2.push([
|
||||
sliced.geometry.coordinates[1][0],
|
||||
sliced.geometry.coordinates[1][1]
|
||||
])
|
||||
}
|
||||
array.push(array2)
|
||||
}
|
||||
|
||||
let viewPoint = Cesium.Cartesian3.fromDegrees(
|
||||
this.center.lng,
|
||||
this.center.lat,
|
||||
this.center.alt + this.viewPointHeight
|
||||
)
|
||||
let instances = []
|
||||
CircleViewShed.getcanvas(this).then(canvas =>
|
||||
this.viewBillboardPrimitive.add({
|
||||
position: viewPoint,
|
||||
image: canvas,
|
||||
width: 200,
|
||||
height: 140,
|
||||
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
disableDepthTestDistance: Number.POSITIVE_INFINITY
|
||||
})
|
||||
)
|
||||
this.viewpointPrimitive.add({
|
||||
position: viewPoint,
|
||||
color: Cesium.Color.AQUA.withAlpha(1),
|
||||
pixelSize: 6
|
||||
})
|
||||
|
||||
let m = 0
|
||||
let _this = this
|
||||
let key = this.randomString()
|
||||
let intervalEvent = setInterval(() => {
|
||||
if (m >= array.length) {
|
||||
let item = this.#intervalEvents.get(key)
|
||||
item && clearInterval(item.event)
|
||||
return
|
||||
}
|
||||
InBatches(m)
|
||||
m += 1
|
||||
}, 0)
|
||||
this.#intervalEvents.set(key, { event: intervalEvent })
|
||||
|
||||
function InBatches(k) {
|
||||
let instances = []
|
||||
let i = k
|
||||
for (let j = 0; j < array[i].length; j++) {
|
||||
let pt1 = array[i][j]
|
||||
let pt2
|
||||
let pt3
|
||||
let pt4 = array[i][j - 1]
|
||||
if (i == array.length - 1) {
|
||||
pt2 = array[0][j]
|
||||
pt3 = array[0][j - 1]
|
||||
} else {
|
||||
pt2 = array[i + 1][j]
|
||||
pt3 = array[i + 1][j - 1]
|
||||
}
|
||||
if (j == 0) {
|
||||
pt3 = [...center]
|
||||
pt4 = []
|
||||
}
|
||||
let cpt = [(pt1[0] + pt3[0]) / 2, (pt1[1] + pt3[1]) / 2]
|
||||
let cartographic = Cesium.Cartographic.fromDegrees(cpt[0], cpt[1])
|
||||
let height = _this.viewer.scene.globe.getHeight(cartographic)
|
||||
let targetPoint = Cesium.Cartesian3.fromDegrees(cpt[0], cpt[1], height)
|
||||
|
||||
let direction = Cesium.Cartesian3.normalize(
|
||||
Cesium.Cartesian3.subtract(
|
||||
targetPoint,
|
||||
viewPoint,
|
||||
new Cesium.Cartesian3()
|
||||
),
|
||||
new Cesium.Cartesian3()
|
||||
)
|
||||
let ray = new Cesium.Ray(viewPoint, direction)
|
||||
let pickedObjects = _this.viewer.scene.drillPickFromRay(
|
||||
ray,
|
||||
_this.primitives
|
||||
)
|
||||
let result
|
||||
for (let i = 0; i < pickedObjects.length; i++) {
|
||||
if (pickedObjects[i].position) {
|
||||
result = pickedObjects[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
let color = Cesium.Color.LIME
|
||||
if (
|
||||
result &&
|
||||
Math.abs(result.position.x - targetPoint.x) > 0.01 &&
|
||||
Math.abs(result.position.y - targetPoint.y) > 0.01 &&
|
||||
Math.abs(result.position.z - targetPoint.z) > 0.01
|
||||
) {
|
||||
color = Cesium.Color.RED
|
||||
}
|
||||
let polyline = new Cesium.GroundPolylineGeometry({
|
||||
positions: Cesium.Cartesian3.fromDegreesArray([
|
||||
...pt1,
|
||||
...pt2,
|
||||
...pt3,
|
||||
...pt4,
|
||||
...pt1
|
||||
]),
|
||||
width: 2
|
||||
})
|
||||
|
||||
let polygonInstance = new Cesium.GeometryInstance({
|
||||
geometry: polyline,
|
||||
name: 'ViewershedPolygon',
|
||||
attributes: {
|
||||
color: Cesium.ColorGeometryInstanceAttribute.fromColor(color),
|
||||
show: new Cesium.ShowGeometryInstanceAttribute(true) //显示或者隐藏
|
||||
}
|
||||
})
|
||||
instances.push(polygonInstance)
|
||||
}
|
||||
|
||||
_this.primitives.push(
|
||||
_this.viewer.scene.primitives.add(
|
||||
new Cesium.GroundPolylinePrimitive({
|
||||
geometryInstances: instances,
|
||||
appearance: new Cesium.PolylineColorAppearance()
|
||||
})
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
static getcanvas(that) {
|
||||
const canvas = document.createElement('canvas')
|
||||
const ctx = canvas.getContext('2d')
|
||||
canvas.width = 220
|
||||
canvas.height = 140
|
||||
canvas.style.background = '#000000'
|
||||
let img = new Image()
|
||||
const data = [
|
||||
{
|
||||
images: that.getSourceRootPath() + '/img/bubble/lng.png',
|
||||
text: '经度:' + parseFloat(that.center.lng.toFixed(10)) + '°'
|
||||
},
|
||||
{
|
||||
images: that.getSourceRootPath() + '/img/bubble/lat.png',
|
||||
text: '纬度:' + parseFloat(that.center.lat.toFixed(10)) + '°'
|
||||
},
|
||||
{
|
||||
images: that.getSourceRootPath() + '/img/bubble/h.png',
|
||||
text: '视高:' + that.viewPointHeight + ' m'
|
||||
},
|
||||
{
|
||||
images: that.getSourceRootPath() + '/img/bubble/radius.png',
|
||||
text: '半径:' + that.radius + ' m'
|
||||
}
|
||||
]
|
||||
img.src = that.getSourceRootPath() + '/img/bubble/bubble.png'
|
||||
let imagesLoaded = 0
|
||||
return new Promise(async (resolve, reject) => {
|
||||
img.onload = () => {
|
||||
ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
|
||||
data.forEach((item, index) => {
|
||||
const img = new Image()
|
||||
img.src = item.images
|
||||
img.onload = () => {
|
||||
ctx.drawImage(img, 12, 12 + index * 26)
|
||||
ctx.fillStyle = '#fff'
|
||||
ctx.font = '12px Arial'
|
||||
ctx.fillText(item.text, 44, 28 + index * 26)
|
||||
imagesLoaded++
|
||||
if (imagesLoaded === data.length) {
|
||||
resolve(canvas)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
destroy() {
|
||||
for (const [key, value] of this.#intervalEvents) {
|
||||
clearInterval(value.event)
|
||||
}
|
||||
this.#intervalEvents = new Map()
|
||||
for (let i = 0; i < this.primitives.length; i++) {
|
||||
this.viewer.scene.primitives.remove(this.primitives[i])
|
||||
}
|
||||
this.primitives = []
|
||||
if (this.viewpointPrimitive) {
|
||||
this.viewer.scene.primitives.remove(this.viewpointPrimitive)
|
||||
this.viewpointPrimitive = null
|
||||
}
|
||||
if (this.viewBillboardPrimitive) {
|
||||
this.viewer.scene.primitives.remove(this.viewBillboardPrimitive)
|
||||
this.viewBillboardPrimitive = null
|
||||
}
|
||||
YJ.Measure.SetMeasureStatus(false)
|
||||
}
|
||||
}
|
||||
|
||||
export default CircleViewShed
|
||||
208
src/Obj/Analysis/Contour/index.js
Normal file
208
src/Obj/Analysis/Contour/index.js
Normal file
@ -0,0 +1,208 @@
|
||||
|
||||
|
||||
import Tools from '../../../Tools';
|
||||
class ContourAnalysis {
|
||||
/**
|
||||
* @constructor 等高线分析
|
||||
* @param sdk
|
||||
* **/
|
||||
constructor(sdk, options = {}) {
|
||||
this.viewer = sdk.viewer
|
||||
let terrainAvailability = this.viewer.terrainProvider.availability;
|
||||
if (!terrainAvailability) {
|
||||
this.error = '未加载地形数据!'
|
||||
window.ELEMENT && window.ELEMENT.Message({
|
||||
message: '未加载地形数据!',
|
||||
type: 'warning',
|
||||
duration: 1500
|
||||
});
|
||||
console.warn(this.error)
|
||||
return
|
||||
}
|
||||
this.positions = options.positions
|
||||
this.interfaceNum = options.interfaceNum || 25 //内插时均分的数量,即沿着边界长或宽均分成n分进行插点,默认值25
|
||||
this.colorFill = options.colorFill || [
|
||||
"#8CEA00",
|
||||
"#B7FF4A",
|
||||
"#FFFF37",
|
||||
"#FFE66F",
|
||||
"#FFD1A4",
|
||||
"#FFCBB3",
|
||||
"#FFBD9D",
|
||||
"#FFAD86",
|
||||
"#FF9D6F",
|
||||
"#FF8F59",
|
||||
"#FF8040",
|
||||
"#FF5809",
|
||||
"#F75000",
|
||||
"#D94600",
|
||||
"#BB3D00",
|
||||
"#A23400",
|
||||
"#842B00",
|
||||
"#642100",
|
||||
"#4D0000",
|
||||
"#2F0000",
|
||||
]; //等高线赋值颜色,内含default值
|
||||
this.countorLineList = Cesium.defaultValue(options.countorLineList, []);
|
||||
YJ.Analysis.Analyses.push(this)
|
||||
this.createNewLine();
|
||||
}
|
||||
createNewLine() {
|
||||
ContourAnalysis.interpolatePoint(this);
|
||||
}
|
||||
|
||||
//利用turf在box内进行插点
|
||||
static interpolatePoint(that) {
|
||||
let curPoints = that.positions
|
||||
let features = [];
|
||||
const boundaryCoord = {
|
||||
minX: 360,
|
||||
maxX: -360,
|
||||
minY: 180,
|
||||
maxY: -180,
|
||||
}; //绘制几何图形的外围矩形box
|
||||
for (let index = 0; index < curPoints.length; index++) {
|
||||
const element = Cesium.Cartesian3.fromDegrees(curPoints[index].lng, curPoints[index].lat, curPoints[index].alt);
|
||||
let ellipsoid = that.viewer.scene.globe.ellipsoid;
|
||||
let cartographic = ellipsoid.cartesianToCartographic(element);
|
||||
let lat = Cesium.Math.toDegrees(cartographic.latitude);
|
||||
let lng = Cesium.Math.toDegrees(cartographic.longitude);
|
||||
boundaryCoord.maxY = Math.max(lat, boundaryCoord.maxY);
|
||||
boundaryCoord.minY = Math.min(lat, boundaryCoord.minY);
|
||||
boundaryCoord.maxX = Math.max(lng, boundaryCoord.maxX);
|
||||
boundaryCoord.minX = Math.min(lng, boundaryCoord.minX);
|
||||
|
||||
let curFeature = {
|
||||
type: "Feature",
|
||||
properties: {},
|
||||
geometry: {
|
||||
type: "Point",
|
||||
coordinates: [lng, lat],
|
||||
},
|
||||
};
|
||||
features.push(curFeature);
|
||||
}
|
||||
let boundaryJson = {
|
||||
type: "FeatureCollection",
|
||||
features: features,
|
||||
};
|
||||
turf.featureEach(boundaryJson, function (point) {
|
||||
point.properties.height = 0;
|
||||
});
|
||||
let options = {
|
||||
gridType: "points",
|
||||
property: "height",
|
||||
units: "kilometers",
|
||||
};
|
||||
let from = turf.point([boundaryCoord.minX, boundaryCoord.minY]);
|
||||
let to = turf.point([boundaryCoord.maxX, boundaryCoord.maxY]);
|
||||
let diagonalDistance = turf.rhumbDistance(from, to, {
|
||||
units: "kilometers",
|
||||
});
|
||||
let grid = turf.interpolate(
|
||||
boundaryJson,
|
||||
diagonalDistance / that.interfaceNum,
|
||||
options
|
||||
);
|
||||
let minHeight = 10000000; //最低点高程值
|
||||
let maxHeight = -100000000; //最高点高程值
|
||||
turf.featureEach(grid, function (point) {
|
||||
let pos = point.geometry.coordinates;
|
||||
let cartographic = Cesium.Cartographic.fromDegrees(pos[0], pos[1]);
|
||||
let height = that.viewer.scene.globe.getHeight(cartographic);
|
||||
maxHeight = Math.max(height, maxHeight);
|
||||
minHeight = Math.min(height, minHeight);
|
||||
point.properties.height = height;
|
||||
});
|
||||
let breaks = [];
|
||||
let stepCount = that.colorFill.length - 1;
|
||||
let step = (maxHeight - minHeight) / stepCount;
|
||||
for (let index = 0; index < stepCount + 1; index++) {
|
||||
breaks.push(Math.ceil(minHeight + step * index));
|
||||
}
|
||||
// console.log('grid', grid)
|
||||
let linesJson = turf.isolines(grid, breaks, { zProperty: "height" });
|
||||
let _countorLine = Cesium.GeoJsonDataSource.load(linesJson, {
|
||||
clampToGround: true,
|
||||
});
|
||||
// console.log(linesJson)
|
||||
_countorLine.then(function (dataSource) {
|
||||
console.log(dataSource)
|
||||
that.countorLine = dataSource; //最终计算生成的等高线对象,GeoJsonDataSource
|
||||
that.countorLineList.push(dataSource); //等高线数组
|
||||
that.viewer.dataSources.add(dataSource);
|
||||
let entities = dataSource.entities.values;
|
||||
for (let index = 0; index < entities.length; index++) {
|
||||
const element = entities[index];
|
||||
let center = getPolylineCenter(element.polyline);
|
||||
element.position = center;
|
||||
// dataSource.entities.add(new Cesium.Entity({
|
||||
// position: center,
|
||||
// label: {
|
||||
// text: element.properties.height._value + '',
|
||||
// font: '20px Microsoft YaHei',
|
||||
// fillColor: Cesium.Color.fromCssColorString('#f1d20c'),
|
||||
// style: Cesium.LabelStyle.FILL_AND_OUTLINE,
|
||||
// disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
||||
// heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
|
||||
// },
|
||||
// }))
|
||||
// element.label = new Cesium.LabelGraphics({
|
||||
|
||||
// })
|
||||
let cur_index = that.getObjectIndex(
|
||||
breaks,
|
||||
element.properties.height._value
|
||||
);
|
||||
if (cur_index) {
|
||||
element.polyline.material = Cesium.Color.fromCssColorString(
|
||||
that.colorFill[cur_index - 1]
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function getPolylineCenter(polyline) {
|
||||
let tools = new Tools()
|
||||
let positions = polyline.positions;
|
||||
let length = positions._value.length;
|
||||
let array = []
|
||||
for (let i = 0; i < length; i++) {
|
||||
let pos = tools.cartesian3Towgs84(positions._value[i], that.viewer)
|
||||
array.push([pos.lng, pos.lat])
|
||||
}
|
||||
let line = turf.lineString(array);
|
||||
let distance = turf.length(line, { units: "kilometers" });
|
||||
let along = turf.along(line, distance/2, { units: "kilometers" });
|
||||
return Cesium.Cartesian3.fromDegrees(along.geometry.coordinates[0], along.geometry.coordinates[1], 0);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 返回随机插入的数在数组中的位置
|
||||
* @param {*} arr 元数组
|
||||
* @param {*} num 随机数
|
||||
* @returns 序号
|
||||
* @example getObjectIndex([0,218,325,333,444],354)=>4;
|
||||
*/
|
||||
getObjectIndex(arr, num) {
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
if (arr[i] > num) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
clear(countorLine) {
|
||||
if (countorLine) {
|
||||
this.viewer.dataSources.remove(countorLine);
|
||||
let index = this.countorLineList.indexOf(countorLine);
|
||||
this.countorLineList.splice(index, 1);
|
||||
}
|
||||
}
|
||||
destroy() {
|
||||
this.countorLineList.forEach((element) => {
|
||||
this.viewer.dataSources.remove(element);
|
||||
});
|
||||
this.countorLineList = [];
|
||||
}
|
||||
}
|
||||
export default ContourAnalysis;
|
||||
125
src/Obj/Analysis/CutFill/CreatePolygon.js
Normal file
125
src/Obj/Analysis/CutFill/CreatePolygon.js
Normal file
@ -0,0 +1,125 @@
|
||||
class CreatePolygon {
|
||||
constructor(viewer) {
|
||||
if (!viewer) throw new Error("no viewer object!");
|
||||
this.activePoints = [];
|
||||
this.viewer = viewer;
|
||||
this.handler = undefined;
|
||||
this.init();
|
||||
}
|
||||
init() {
|
||||
this.activeShapePoints = [];
|
||||
this.floatingPoint = undefined;
|
||||
this.activeShape = undefined;
|
||||
this.activePoints.forEach((element) => {
|
||||
this.viewer.entities.remove(element);
|
||||
});
|
||||
this.activePoints = [];
|
||||
this.initHandler();
|
||||
}
|
||||
start(callback) {
|
||||
const $this = this;
|
||||
$this.keyDownStatus(true);
|
||||
$this.init();
|
||||
$this.handler = new Cesium.ScreenSpaceEventHandler($this.viewer.canvas);
|
||||
$this.handler.setInputAction(function (event) {
|
||||
let earthPosition = $this.viewer.scene.pickPosition(event.position);
|
||||
if (Cesium.defined(earthPosition)) {
|
||||
if ($this.activeShapePoints.length === 0) {
|
||||
$this.floatingPoint = $this.createPoint(earthPosition);
|
||||
$this.activeShapePoints.push(earthPosition);
|
||||
let dynamicPositions = new Cesium.CallbackProperty(function () {
|
||||
return new Cesium.PolygonHierarchy($this.activeShapePoints);
|
||||
}, false);
|
||||
$this.activeShape = $this.drawShape(dynamicPositions); //绘制动态图
|
||||
}
|
||||
$this.activeShapePoints.push(earthPosition);
|
||||
$this.createPoint(earthPosition);
|
||||
}
|
||||
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
|
||||
$this.handler.setInputAction(function (event) {
|
||||
if (Cesium.defined($this.floatingPoint)) {
|
||||
let newPosition = $this.viewer.scene.pickPosition(event.endPosition);
|
||||
if (Cesium.defined(newPosition)) {
|
||||
$this.floatingPoint.position.setValue(newPosition);
|
||||
$this.activeShapePoints.pop();
|
||||
$this.activeShapePoints.push(newPosition);
|
||||
}
|
||||
}
|
||||
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
|
||||
$this.handler.setInputAction(function () {
|
||||
$this.activeShapePoints.pop(); //去除最后一个动态点
|
||||
if ($this.activeShapePoints.length) {
|
||||
$this.polygon = $this.drawShape($this.activeShapePoints); //绘制最终图
|
||||
}
|
||||
$this.viewer.entities.remove($this.floatingPoint); //去除动态点图形(当前鼠标点)
|
||||
$this.viewer.entities.remove($this.activeShape); //去除动态图形
|
||||
$this.activePoints.forEach((element) => {
|
||||
$this.viewer.entities.remove(element);
|
||||
});
|
||||
$this.handler.destroy();
|
||||
setTimeout(() => {
|
||||
if (typeof callback == "function") callback();
|
||||
}, 1000);
|
||||
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
|
||||
}
|
||||
initHandler() {
|
||||
if (this.handler) {
|
||||
this.handler.destroy();
|
||||
this.handler = undefined;
|
||||
}
|
||||
}
|
||||
createPoint(worldPosition) {
|
||||
let point = this.viewer.entities.add({
|
||||
position: worldPosition,
|
||||
point: {
|
||||
color: Cesium.Color.SKYBLUE,
|
||||
pixelSize: 5,
|
||||
},
|
||||
});
|
||||
this.activePoints.push(point);
|
||||
return point;
|
||||
}
|
||||
drawShape(positionData) {
|
||||
let shape = this.viewer.entities.add({
|
||||
polygon: {
|
||||
hierarchy: positionData,
|
||||
material: new Cesium.ColorMaterialProperty(
|
||||
Cesium.Color.BLUE.withAlpha(0.4)
|
||||
),
|
||||
zIndex: 99999999
|
||||
},
|
||||
});
|
||||
return shape;
|
||||
}
|
||||
//快捷键//Ctrl + Z
|
||||
keyDownStatus(bool) {
|
||||
const $this = this;
|
||||
document.onkeydown = function (event) {
|
||||
if (event.ctrlKey && window.event.keyCode == 90) {
|
||||
if (!bool) {
|
||||
return false;
|
||||
}
|
||||
$this.activeShapePoints.pop();
|
||||
$this.viewer.entities.remove(
|
||||
$this.activePoints[$this.activePoints.length - 1]
|
||||
);
|
||||
$this.activePoints.pop();
|
||||
}
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Cesium中世界坐标系(笛卡尔)转经纬度
|
||||
* @param {*} cartesian3
|
||||
* @returns 经纬度
|
||||
*/
|
||||
Cartesian3ToDgrees(cartesian3) {
|
||||
let cartographic =
|
||||
window.viewer.scene.globe.ellipsoid.cartesianToCartographic(cartesian3);
|
||||
let lat = Cesium.Math.toDegrees(cartographic.latitude);
|
||||
let lng = Cesium.Math.toDegrees(cartographic.longitude);
|
||||
let alt = cartographic.height;
|
||||
return { lng: lng, lat: lat, alt: alt };
|
||||
}
|
||||
}
|
||||
|
||||
export default CreatePolygon;
|
||||
75
src/Obj/Analysis/CutFill/_element.js
Normal file
75
src/Obj/Analysis/CutFill/_element.js
Normal file
@ -0,0 +1,75 @@
|
||||
function html() {
|
||||
return `
|
||||
<span class="custom-divider"></span>
|
||||
<div class="div-item">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<span class="label" style="flex: 0 0 70px;">绘制分析区域</span>
|
||||
<button class="draw-btn"><svg class="icon-edit"><use xlink:href="#yj-icon-edit"></use></svg>开始绘制</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="custom-divider"></span>
|
||||
<div class="div-item">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<span class="label">基准高度</span>
|
||||
<div class="input-number input-number-unit-1">
|
||||
<input class="input" type="number" title="" min="-999999" max="999999" name="height">
|
||||
<span class="unit">m</span>
|
||||
<span class="arrow"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<span class="label">精度</span>
|
||||
<div class="input-number input-number-unit">
|
||||
<input class="input" type="number" title="" min="1" max="1250" name="precision">
|
||||
<span class="arrow"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="custom-divider"></span>
|
||||
<div class="div-item">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<span class="label" style="flex: 0 0 74px;">总分析面积:</span>
|
||||
<span class="text-number" name="allArea">0</span>
|
||||
<span class="unit text-number">m²</span>
|
||||
</div>
|
||||
<div class="col">
|
||||
<span class="label" style="flex: 0 0 90px;">无须填挖面积:</span>
|
||||
<span class="text-number" name="noArea">0</span>
|
||||
<span class="unit text-number">m²</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<span class="label" style="flex: 0 0 74px;">填方面积:</span>
|
||||
<span class="text-number" name="fillArea">0</span>
|
||||
<span class="unit text-number">m²</span>
|
||||
</div>
|
||||
<div class="col">
|
||||
<span class="label" style="flex: 0 0 90px;">挖方面积:</span>
|
||||
<span class="text-number" name="cutArea">0</span>
|
||||
<span class="unit text-number">m²</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<span class="label" style="flex: 0 0 74px;">填方体积:</span>
|
||||
<span class="text-number" name="fillVolume">0</span>
|
||||
<span class="unit text-number">m³</span>
|
||||
</div>
|
||||
<div class="col">
|
||||
<span class="label" style="flex: 0 0 90px;">挖方体积:</span>
|
||||
<span class="text-number" name="cutVolume">0</span>
|
||||
<span class="unit text-number">m³</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="custom-divider"></span>
|
||||
`
|
||||
}
|
||||
|
||||
export { html }
|
||||
354
src/Obj/Analysis/CutFill/index.js
Normal file
354
src/Obj/Analysis/CutFill/index.js
Normal file
@ -0,0 +1,354 @@
|
||||
import Dialog from '../../../BaseDialog';
|
||||
import { html } from "./_element";
|
||||
// import CreatePolygon from "./CreatePolygon";
|
||||
import DrawPolygon from "../../../Draw/drawPolygon"
|
||||
|
||||
class CutFillAnalysis {
|
||||
/**
|
||||
* @constructor 填挖方分析
|
||||
* @param sdk
|
||||
* **/
|
||||
constructor(sdk, options = {}, _Dialog = {}) {
|
||||
this.sdk = sdk;
|
||||
this.viewer = sdk.viewer;
|
||||
// if (!positions) throw new Error("no positions object!");
|
||||
// this.positions = positions;
|
||||
this.height = options.height || 70
|
||||
this.maxHeigh = -1000000;
|
||||
this.precision = options.precision || 125
|
||||
this.Dialog = _Dialog
|
||||
this.result = {
|
||||
allArea: "",
|
||||
cutArea: "",
|
||||
cutVolume: "",
|
||||
fillArea: "",
|
||||
fillVolume: "",
|
||||
noArea: "",
|
||||
}
|
||||
this.entities = []
|
||||
this.Draw = new DrawPolygon(this.sdk)
|
||||
YJ.Analysis.Analyses.push(this)
|
||||
CutFillAnalysis.EditBox(this)
|
||||
}
|
||||
|
||||
create() {
|
||||
this.clean()
|
||||
this.Draw.start((a, positions) => {
|
||||
if(!positions || positions.length<3) {
|
||||
let _error = '最少需要三个坐标!'
|
||||
console.warn(_error)
|
||||
window.ELEMENT && window.ELEMENT.Message({
|
||||
message: _error,
|
||||
type: 'warning',
|
||||
duration: 1500
|
||||
});
|
||||
return
|
||||
}
|
||||
let fromDegreesArray = []
|
||||
for (let i = 0; i < positions.length; i++) {
|
||||
fromDegreesArray.push(positions[i].lng, positions[i].lat, positions[i].alt)
|
||||
}
|
||||
this.positions = Cesium.Cartesian3.fromDegreesArrayHeights(fromDegreesArray)
|
||||
this.createPolygonGeo(this.positions);
|
||||
this.result = this.VolumeAnalysis();
|
||||
this.viewer.scene.screenSpaceCameraController.enableCollisionDetection = false; //允许相机进入地下
|
||||
})
|
||||
// const $this = this;
|
||||
// if (!this.cp) {
|
||||
// this.cp = new CreatePolygon(this.viewer)
|
||||
// }
|
||||
// this.cp.start(function () {
|
||||
// console.log($this.cp.activeShapePoints)
|
||||
// $this.positions = $this.cp.activeShapePoints;
|
||||
// $this.createPolygonGeo($this.positions);
|
||||
// $this.result = $this.VolumeAnalysis();
|
||||
// $this.viewer.entities.remove($this.cp.polygon);
|
||||
// $this.viewer.scene.screenSpaceCameraController.enableCollisionDetection = false; //允许相机进入地下
|
||||
|
||||
// });
|
||||
}
|
||||
createPolygonGeo(points) {
|
||||
//计算网格粒度-精度
|
||||
let granularity = Math.PI / Math.pow(2, 11);
|
||||
granularity = granularity / this.precision;
|
||||
let polygonGeometry = new Cesium.PolygonGeometry.fromPositions({
|
||||
positions: points,
|
||||
vertexFormat: Cesium.PerInstanceColorAppearance.FLAT_VERTEX_FORMAT,
|
||||
granularity: granularity,
|
||||
});
|
||||
//创建自定义平面几何体
|
||||
this.geom = new Cesium.PolygonGeometry.createGeometry(polygonGeometry);
|
||||
}
|
||||
VolumeAnalysis() {
|
||||
let cutArea = 0,
|
||||
cutVolume = 0,
|
||||
fillArea = 0,
|
||||
fillVolume = 0,
|
||||
noArea = 0;
|
||||
const indices = this.geom.indices; //获取顶点索引数据
|
||||
if (!this.geom || !this.geom.attributes || !this.geom.attributes.position) {
|
||||
return;
|
||||
}
|
||||
const positions = this.geom.attributes.position.values;
|
||||
for (let index = 0; index < indices.length; index += 3) {
|
||||
const pos0 = this.returnPosition(positions, indices[index]);
|
||||
const pos1 = this.returnPosition(positions, indices[index + 1]);
|
||||
const pos2 = this.returnPosition(positions, indices[index + 2]);
|
||||
let entity = this.viewer.entities.add({
|
||||
name: "三角面",
|
||||
polygon: {
|
||||
hierarchy: [pos0.heightPos, pos1.heightPos, pos2.heightPos],
|
||||
perPositionHeight: true,
|
||||
material: Cesium.Color.fromRandom(),
|
||||
extrudedHeight: this.height,
|
||||
outline: true,
|
||||
outlineColor: Cesium.Color.BLACK,
|
||||
},
|
||||
});
|
||||
this.entities.push(entity)
|
||||
//水平状态下三角形面积
|
||||
const area = this.computeArea4Triangle(
|
||||
pos0.noHeightPos,
|
||||
pos1.noHeightPos,
|
||||
pos2.noHeightPos
|
||||
);
|
||||
//计算三个点的均高
|
||||
const height = (pos0.height + pos1.height + pos2.height) / 3;
|
||||
if (height < this.height) {
|
||||
// 需要填方的部分
|
||||
fillArea += area;
|
||||
const volume = area * (this.height - height);
|
||||
fillVolume += volume;
|
||||
} else if (height == this.height) {
|
||||
noArea += area;
|
||||
} else {
|
||||
// 需要挖方的部分
|
||||
cutArea += area;
|
||||
const volume = area * (height - this.height);
|
||||
cutVolume += volume;
|
||||
}
|
||||
}
|
||||
const allArea = cutArea + fillArea + noArea;
|
||||
// this.result = {
|
||||
// allArea,
|
||||
// cutArea,
|
||||
// cutVolume,
|
||||
// fillArea,
|
||||
// fillVolume,
|
||||
// noArea,
|
||||
// };
|
||||
this.result.allArea = allArea
|
||||
this.result.cutArea = cutArea
|
||||
this.result.cutVolume = cutVolume
|
||||
this.result.fillArea = fillArea
|
||||
this.result.fillVolume = fillVolume
|
||||
this.result.noArea = noArea
|
||||
return this.result;
|
||||
}
|
||||
computeCentroid4Polygon(positions) {
|
||||
let x = [],
|
||||
y = [];
|
||||
let allX = 0,
|
||||
allY = 0;
|
||||
for (let i = 0; i < positions.length; i++) {
|
||||
let cartographic = Cesium.Cartographic.fromCartesian(positions[i]);
|
||||
allX += cartographic.longitude;
|
||||
allY += cartographic.latitude;
|
||||
x.push(cartographic.longitude);
|
||||
y.push(cartographic.latitude);
|
||||
}
|
||||
let centroidx = allX / positions.length;
|
||||
let centroidy = allY / positions.length;
|
||||
const Cartographic = new Cesium.Cartographic(centroidx, centroidy);
|
||||
return Cesium.Cartesian3.fromRadians(
|
||||
Cartographic.longitude,
|
||||
Cartographic.latitude,
|
||||
this.maxHeigh + 30
|
||||
);
|
||||
}
|
||||
/**
|
||||
* 海伦公式求取三角形面积
|
||||
* @param {*} pos1
|
||||
* @param {*} pos2
|
||||
* @param {*} pos3
|
||||
* @returns 三角形面积㎡
|
||||
*/
|
||||
computeArea4Triangle(pos1, pos2, pos3) {
|
||||
let a = Cesium.Cartesian3.distance(pos1, pos2);
|
||||
let b = Cesium.Cartesian3.distance(pos2, pos3);
|
||||
let c = Cesium.Cartesian3.distance(pos3, pos1);
|
||||
let S = (a + b + c) / 2;
|
||||
return Math.sqrt(S * (S - a) * (S - b) * (S - c));
|
||||
}
|
||||
returnPosition(positions, index) {
|
||||
let cartesian = new Cesium.Cartesian3(
|
||||
positions[index * 3],
|
||||
positions[index * 3 + 1],
|
||||
positions[index * 3 + 2]
|
||||
);
|
||||
let cartographic = Cesium.Cartographic.fromCartesian(cartesian);
|
||||
let height = this.viewer.scene.sampleHeightSupported
|
||||
? this.viewer.scene.sampleHeight(cartographic)
|
||||
: this.viewer.scene.globe.getHeight(cartographic);
|
||||
if (height > this.maxHeigh) {
|
||||
this.maxHeigh = height;
|
||||
}
|
||||
return {
|
||||
heightPos: Cesium.Cartesian3.fromRadians(
|
||||
cartographic.longitude,
|
||||
cartographic.latitude,
|
||||
height
|
||||
),
|
||||
noHeightPos: Cesium.Cartesian3.fromRadians(
|
||||
cartographic.longitude,
|
||||
cartographic.latitude,
|
||||
0
|
||||
),
|
||||
height: height,
|
||||
};
|
||||
}
|
||||
|
||||
static async EditBox(that) {
|
||||
if (that._DialogObject && that._DialogObject.close) {
|
||||
that._DialogObject.close()
|
||||
that._DialogObject = null
|
||||
}
|
||||
that._DialogObject = await new Dialog(that.sdk.viewer._container, {
|
||||
title: '土方分析', left: '180px', top: '100px',
|
||||
closeCallBack: () => {
|
||||
that.clean()
|
||||
that.Dialog.closeCallBack && that.Dialog.closeCallBack()
|
||||
},
|
||||
})
|
||||
await that._DialogObject.init()
|
||||
let contentElm = document.createElement('div');
|
||||
contentElm.innerHTML = html()
|
||||
that._DialogObject.contentAppChild(contentElm)
|
||||
that._DialogObject._element.body.className = that._DialogObject._element.body.className + ' cut-fill'
|
||||
|
||||
// 高度值
|
||||
let e_height = contentElm.querySelector("input[name='height']")
|
||||
e_height.value = that.height
|
||||
e_height.addEventListener('blur', (e) => {
|
||||
let value = e.target.value
|
||||
if (e.data != '.' && (e.data != '-' || e.target.value)) {
|
||||
value = Number(value)
|
||||
if ((e.target.max) && value > Number(e.target.max)) {
|
||||
value = Number(e.target.max)
|
||||
}
|
||||
if ((e.target.min) && value < Number(e.target.min)) {
|
||||
value = Number(e.target.min)
|
||||
}
|
||||
e_height.value = value
|
||||
that.height = e_height.value;
|
||||
}
|
||||
});
|
||||
|
||||
// 精度值
|
||||
let e_precision = contentElm.querySelector("input[name='precision']")
|
||||
e_precision.value = that.precision
|
||||
e_precision.addEventListener('blur', (e) => {
|
||||
let value = Number(e.target.value)
|
||||
if ((e.target.max) && value > Number(e.target.max)) {
|
||||
value = Number(e.target.max)
|
||||
}
|
||||
if ((e.target.min) && value < Number(e.target.min)) {
|
||||
value = Number(e.target.min)
|
||||
}
|
||||
e_precision.value = value
|
||||
that.precision = e_precision.value;
|
||||
});
|
||||
|
||||
// 总分析面积
|
||||
let e_allArea = contentElm.querySelector("span[name='allArea']")
|
||||
e_allArea.innerHTML = that.result.allArea || 0
|
||||
Object.defineProperty(that.result, 'allArea', {
|
||||
get() {
|
||||
return e_allArea.innerHTML
|
||||
},
|
||||
set(value) {
|
||||
e_allArea.innerHTML = Number(value.toFixed(4))
|
||||
}
|
||||
})
|
||||
// 填方面积
|
||||
let e_fillArea = contentElm.querySelector("span[name='fillArea']")
|
||||
e_fillArea.innerHTML = that.result.fillArea || 0
|
||||
Object.defineProperty(that.result, 'fillArea', {
|
||||
get() {
|
||||
return e_fillArea.innerHTML
|
||||
},
|
||||
set(value) {
|
||||
e_fillArea.innerHTML = Number(value.toFixed(4))
|
||||
}
|
||||
})
|
||||
|
||||
// 填方体积
|
||||
let e_fillVolume = contentElm.querySelector("span[name='fillVolume']")
|
||||
e_fillVolume.innerHTML = that.result.fillVolume || 0
|
||||
Object.defineProperty(that.result, 'fillVolume', {
|
||||
get() {
|
||||
return e_fillVolume.innerHTML
|
||||
},
|
||||
set(value) {
|
||||
e_fillVolume.innerHTML = Number(value.toFixed(4))
|
||||
}
|
||||
})
|
||||
|
||||
// 挖方面积
|
||||
let e_cutArea = contentElm.querySelector("span[name='cutArea']")
|
||||
e_cutArea.innerHTML = that.result.cutArea || 0
|
||||
Object.defineProperty(that.result, 'cutArea', {
|
||||
get() {
|
||||
return e_cutArea.innerHTML
|
||||
},
|
||||
set(value) {
|
||||
e_cutArea.innerHTML = Number(value.toFixed(4))
|
||||
}
|
||||
})
|
||||
|
||||
// 挖方体积
|
||||
let e_cutVolume = contentElm.querySelector("span[name='cutVolume']")
|
||||
e_cutVolume.innerHTML = that.result.cutVolume || 0
|
||||
Object.defineProperty(that.result, 'cutVolume', {
|
||||
get() {
|
||||
return e_cutVolume.innerHTML
|
||||
},
|
||||
set(value) {
|
||||
e_cutVolume.innerHTML = Number(value.toFixed(4))
|
||||
}
|
||||
})
|
||||
|
||||
// 无须填挖面积
|
||||
let e_noArea = contentElm.querySelector("span[name='noArea']")
|
||||
e_noArea.innerHTML = that.result.noArea || 0
|
||||
Object.defineProperty(that.result, 'noArea', {
|
||||
get() {
|
||||
return e_noArea.innerHTML
|
||||
},
|
||||
set(value) {
|
||||
e_noArea.innerHTML = Number(value.toFixed(4))
|
||||
}
|
||||
})
|
||||
|
||||
let newDivBtn = contentElm.getElementsByClassName('draw-btn')[0];
|
||||
newDivBtn.addEventListener('click', () => {
|
||||
that.create()
|
||||
});
|
||||
}
|
||||
|
||||
clean() {
|
||||
this.Draw && this.Draw.end()
|
||||
for (let i = 0; i < this.entities.length; i++) {
|
||||
this.viewer.entities.remove(this.entities[i])
|
||||
}
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.clean()
|
||||
if (this._DialogObject && this._DialogObject.close) {
|
||||
this._DialogObject.close()
|
||||
this._DialogObject = null
|
||||
}
|
||||
}
|
||||
}
|
||||
export default CutFillAnalysis;
|
||||
483
src/Obj/Analysis/Flat/index.js
Normal file
483
src/Obj/Analysis/Flat/index.js
Normal file
@ -0,0 +1,483 @@
|
||||
import Base from "../../Base/index";
|
||||
import Dialog from '../../../BaseDialog'
|
||||
import { setActiveViewer, closeRotateAround, closeViewFollow} from '../../../Global/global'
|
||||
|
||||
let FlatList = {}
|
||||
class Flat extends Base {
|
||||
/**
|
||||
* @constructor
|
||||
* @description 模型压平
|
||||
* @param sdk
|
||||
* @param {Cesium.Cesium3DTileset} tileset 三维模型
|
||||
* @param {Object} options
|
||||
* @param {string} attr.id id
|
||||
* @param {Cesium.Cartesian3[]} attr.positions 压平面坐标
|
||||
*/
|
||||
constructor(sdk, tileset, options = {}, _Dialog = {}) {
|
||||
super(sdk)
|
||||
if (!tileset || !this.sdk || !this.sdk.viewer) return;
|
||||
this.options = { ...options }
|
||||
this.options.id = options.id || this.randomString()
|
||||
this.options.name = options.name || '压平面'
|
||||
this.options.positions = options.positions || []
|
||||
this.options.show = (options.show || options.show === false) ? options.show : true
|
||||
this.tileset = tileset;
|
||||
this.Dialog = _Dialog
|
||||
|
||||
if (!this.options.height && this.options.height !== 0) {
|
||||
let height = this.options.positions[0].alt
|
||||
for (let i = 0; i < this.options.positions.length; i++) {
|
||||
if (height > this.options.positions[i].alt) {
|
||||
height = this.options.positions[i].alt
|
||||
}
|
||||
}
|
||||
this.options.height = height
|
||||
}
|
||||
|
||||
if (FlatList[this.tileset.id]) {
|
||||
FlatList[this.tileset.id].push({ ...this.options })
|
||||
}
|
||||
else {
|
||||
FlatList[this.tileset.id] = [{ ...this.options }]
|
||||
}
|
||||
|
||||
this.center = tileset.boundingSphere.center.clone();
|
||||
this.center84 = this.cartesian3Towgs84(this.center, this.sdk.viewer)
|
||||
this.matrix = Cesium.Transforms.eastNorthUpToFixedFrame(this.center.clone());
|
||||
this.localMatrix = Cesium.Matrix4.inverse(this.matrix, new Cesium.Matrix4());
|
||||
// this.entity = {
|
||||
// id: this.options.id
|
||||
// }
|
||||
this.addFlat()
|
||||
// Flat.createPolygon(this)
|
||||
}
|
||||
|
||||
get show() {
|
||||
return this.options.show
|
||||
}
|
||||
|
||||
set show(v) {
|
||||
this.options.show = v
|
||||
for (let i = 0; i < FlatList[this.tileset.id].length; i++) {
|
||||
if (FlatList[this.tileset.id][i].id == this.options.id) {
|
||||
FlatList[this.tileset.id][i].show = v
|
||||
}
|
||||
}
|
||||
this.addFlat()
|
||||
}
|
||||
|
||||
get height() {
|
||||
return this.options.height
|
||||
}
|
||||
|
||||
set height(v) {
|
||||
this.options.height = Number(v)
|
||||
for (let i = 0; i < FlatList[this.tileset.id].length; i++) {
|
||||
if (FlatList[this.tileset.id][i].id == this.options.id) {
|
||||
FlatList[this.tileset.id][i].height = Number(v)
|
||||
}
|
||||
}
|
||||
this.addFlat()
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this.options.name
|
||||
}
|
||||
|
||||
set name(v) {
|
||||
this.options.name = v
|
||||
for (let i = 0; i < FlatList[this.tileset.id].length; i++) {
|
||||
if (FlatList[this.tileset.id][i].id == this.options.id) {
|
||||
FlatList[this.tileset.id][i].name = v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addFlat() {
|
||||
let localPositionsArr = []
|
||||
for (let i = 0; i < FlatList[this.tileset.id].length; i++) {
|
||||
let item = FlatList[this.tileset.id][i];
|
||||
if (item.show) {
|
||||
const positions = item.positions;
|
||||
let height = item.height
|
||||
let fromDegreesArray = []
|
||||
for (let i = 0; i < positions.length; i++) {
|
||||
fromDegreesArray.push(positions[i].lng, positions[i].lat)
|
||||
}
|
||||
FlatList[this.tileset.id][i].flatHeight = height - this.center84.alt
|
||||
let localCoor = this.cartesiansToLocal(Cesium.Cartesian3.fromDegreesArray(fromDegreesArray));
|
||||
localPositionsArr.push(localCoor);
|
||||
}
|
||||
}
|
||||
|
||||
const funstr = this.getIsinPolygonFun(localPositionsArr);
|
||||
let str = ``;
|
||||
for (let i = 0; i < localPositionsArr.length; i++) {
|
||||
const coors = localPositionsArr[i];
|
||||
const n = coors.length;
|
||||
let instr = ``;
|
||||
coors.forEach((coordinate, index) => {
|
||||
instr += `points_${n}[${index}] = vec2(${coordinate[0]}, ${coordinate[1]});\n`;
|
||||
})
|
||||
str += `
|
||||
${instr}
|
||||
if(isPointInPolygon_${n}(position2D)){
|
||||
vec4 tileset_local_position_transformed = vec4(tileset_local_position.x, tileset_local_position.y, ground_z + ${FlatList[this.tileset.id][i].flatHeight}, 1.0);
|
||||
vec4 model_local_position_transformed = czm_inverseModel * u_tileset_localToWorldMatrix * tileset_local_position_transformed;
|
||||
|
||||
vsOutput.positionMC.xy = model_local_position_transformed.xy;
|
||||
vsOutput.positionMC.z = model_local_position_transformed.z+ modelMC.z*0.002;
|
||||
return;
|
||||
}`;
|
||||
|
||||
}
|
||||
|
||||
this.updateShader(funstr, str);
|
||||
}
|
||||
|
||||
// static createPolygon(that) {
|
||||
// let color = '#ffffff'
|
||||
// let linecolor = '#000000'
|
||||
// let positions = that.options.positions
|
||||
// let fromDegreesArray = []
|
||||
// for (let i = 0; i < positions.length; i++) {
|
||||
// fromDegreesArray.push(positions[i].lng, positions[i].lat, that.options.height)
|
||||
// }
|
||||
// that.positions = Cesium.Cartesian3.fromDegreesArrayHeights(fromDegreesArray)
|
||||
// that.entity = that.sdk.viewer.entities.add({
|
||||
// show: that.options.show,
|
||||
// id: that.options.id,
|
||||
// polyline: {
|
||||
// positions: [...that.positions, that.positions[0], that.positions[1]],
|
||||
// width: 2,
|
||||
// material: Cesium.Color.fromCssColorString(linecolor),
|
||||
// depthFailMaterial: new Cesium.PolylineDashMaterialProperty({
|
||||
// color: Cesium.Color.YELLOW
|
||||
// }),
|
||||
// clampToGround: false,
|
||||
// zIndex: that.sdk._entityZIndex
|
||||
// },
|
||||
// })
|
||||
// that.sdk._entityZIndex++
|
||||
// }
|
||||
|
||||
remove() {
|
||||
FlatList[this.tileset.id] = FlatList[this.tileset.id].filter((attr) => {
|
||||
return attr.id != this.options.id;
|
||||
})
|
||||
|
||||
let localPositionsArr = [];
|
||||
for (let i = 0; i < FlatList[this.tileset.id].length; i++) {
|
||||
let item = FlatList[this.tileset.id][i];
|
||||
if (item.show) {
|
||||
const positions = item.positions;
|
||||
let height = item.height
|
||||
let fromDegreesArray = []
|
||||
for (let i = 0; i < positions.length; i++) {
|
||||
fromDegreesArray.push(positions[i].lng, positions[i].lat)
|
||||
}
|
||||
FlatList[this.tileset.id][i].flatHeight = height - this.center84.alt
|
||||
let localCoor = this.cartesiansToLocal(Cesium.Cartesian3.fromDegreesArray(fromDegreesArray));
|
||||
localPositionsArr.push(localCoor);
|
||||
}
|
||||
}
|
||||
|
||||
const funstr = this.getIsinPolygonFun(localPositionsArr);
|
||||
let str = ``;
|
||||
for (let i = 0; i < localPositionsArr.length; i++) {
|
||||
const coors = localPositionsArr[i];
|
||||
const n = coors.length;
|
||||
let instr = ``;
|
||||
coors.forEach((coordinate, index) => {
|
||||
instr += `points_${n}[${index}] = vec2(${coordinate[0]}, ${coordinate[1]});\n`;
|
||||
})
|
||||
str += `
|
||||
${instr}
|
||||
if(isPointInPolygon_${n}(position2D)){
|
||||
vec4 tileset_local_position_transformed = vec4(tileset_local_position.x, tileset_local_position.y, ground_z + ${FlatList[this.tileset.id][i].flatHeight}, 1.0);
|
||||
vec4 model_local_position_transformed = czm_inverseModel * u_tileset_localToWorldMatrix * tileset_local_position_transformed;
|
||||
vsOutput.positionMC.xy = model_local_position_transformed.xy;
|
||||
vsOutput.positionMC.z = model_local_position_transformed.z+ modelMC.z*0.002;
|
||||
return;
|
||||
}`;
|
||||
|
||||
}
|
||||
this.updateShader(funstr, str);
|
||||
}
|
||||
|
||||
// 根据数组长度,构建 判断点是否在面内 的压平函数
|
||||
getIsinPolygonFun(polygons) {
|
||||
let pmap = polygons.map((polygon) => polygon.length);
|
||||
let uniqueArray = this.getUniqueArray(pmap);
|
||||
let str = ``;
|
||||
uniqueArray.forEach(length => {
|
||||
str += `
|
||||
vec2 points_${length}[${length}];
|
||||
bool isPointInPolygon_${length}(vec2 point){
|
||||
int nCross = 0; // 交点数
|
||||
const int n = ${length};
|
||||
for(int i = 0; i < n; i++){
|
||||
vec2 p1 = points_${length}[i];
|
||||
vec2 p2 = points_${length}[int(mod(float(i+1),float(n)))];
|
||||
if(p1[1] == p2[1]){
|
||||
continue;
|
||||
}
|
||||
if(point[1] < min(p1[1], p2[1])){
|
||||
continue;
|
||||
}
|
||||
if(point[1] >= max(p1[1], p2[1])){
|
||||
continue;
|
||||
}
|
||||
float x = p1[0] + ((point[1] - p1[1]) * (p2[0] - p1[0])) / (p2[1] - p1[1]);
|
||||
if(x > point[0]){
|
||||
nCross++;
|
||||
}
|
||||
}
|
||||
return int(mod(float(nCross), float(2))) == 1;
|
||||
}
|
||||
`
|
||||
})
|
||||
return str
|
||||
}
|
||||
|
||||
updateShader(vtx1, vtx2) {
|
||||
let flatCustomShader = new Cesium.CustomShader({
|
||||
uniforms: {
|
||||
u_tileset_localToWorldMatrix: {
|
||||
type: Cesium.UniformType.MAT4,
|
||||
value: this.matrix,
|
||||
},
|
||||
u_tileset_worldToLocalMatrix: {
|
||||
type: Cesium.UniformType.MAT4,
|
||||
value: this.localMatrix,
|
||||
},
|
||||
u_flatHeight: {
|
||||
type: Cesium.UniformType.FLOAT,
|
||||
value: this.flatHeight,
|
||||
},
|
||||
},
|
||||
vertexShaderText: `
|
||||
// 所有isPointInPolygon函数
|
||||
${vtx1}
|
||||
void vertexMain(VertexInput vsInput, inout czm_modelVertexOutput vsOutput){
|
||||
vec3 modelMC = vsInput.attributes.positionMC;
|
||||
vec4 model_local_position = vec4(modelMC.x, modelMC.y, modelMC.z, 1.0);
|
||||
vec4 tileset_local_position = u_tileset_worldToLocalMatrix * czm_model * model_local_position;
|
||||
vec2 position2D = vec2(tileset_local_position.x,tileset_local_position.y);
|
||||
float ground_z = 0.0;
|
||||
// 多个多边形区域
|
||||
${vtx2}
|
||||
}`,
|
||||
});
|
||||
this.tileset.customShader = flatCustomShader;
|
||||
this.sdk.viewer.scene.requestRender();
|
||||
|
||||
}
|
||||
|
||||
// 数组去重,不能处理嵌套的数组
|
||||
getUniqueArray = (arr) => {
|
||||
return arr.filter(function (item, index, arr) {
|
||||
//当前元素,在原始数组中的第一个索引==当前索引值,否则返回当前元素
|
||||
return arr.indexOf(item, 0) === index;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// 世界坐标转数组局部坐标
|
||||
cartesiansToLocal(positions) {
|
||||
let arr = [];
|
||||
for (let i = 0; i < positions.length; i++) {
|
||||
let position = positions[i];
|
||||
let localp = Cesium.Matrix4.multiplyByPoint(
|
||||
this.localMatrix,
|
||||
position.clone(),
|
||||
new Cesium.Cartesian3()
|
||||
)
|
||||
arr.push([localp.x, localp.y]);
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* 飞到
|
||||
*/
|
||||
async flyTo() {
|
||||
setActiveViewer(0)
|
||||
closeRotateAround(this.sdk)
|
||||
closeViewFollow(this.sdk)
|
||||
|
||||
if (this.options.customView && this.options.customView.relativePosition && this.options.customView.orientation) {
|
||||
let orientation = {
|
||||
heading: Cesium.Math.toRadians(this.options.customView.orientation.heading || 0.0),
|
||||
pitch: Cesium.Math.toRadians(this.options.customView.orientation.pitch || -60.0),
|
||||
roll: Cesium.Math.toRadians(this.options.customView.orientation.roll || 0.0)
|
||||
}
|
||||
|
||||
let lng = this.options.customView.relativePosition.lng
|
||||
let lat = this.options.customView.relativePosition.lat
|
||||
let alt = this.options.customView.relativePosition.alt
|
||||
let destination = Cesium.Cartesian3.fromDegrees(lng, lat, alt)
|
||||
|
||||
let position = { lng: 0, lat: 0 }
|
||||
if (this.options.position) {
|
||||
position = { ...this.options.position }
|
||||
}
|
||||
else if (this.options.positions) {
|
||||
position = { ...this.options.positions[0] }
|
||||
}
|
||||
else if (this.options.line && this.options.line.positions) {
|
||||
position = { ...this.options.line.positions[0] }
|
||||
}
|
||||
else if (this.options.center) {
|
||||
position = { ...this.options.center }
|
||||
}
|
||||
else if (this.options.start) {
|
||||
position = { ...this.options.start }
|
||||
}
|
||||
else {
|
||||
if (this.options.hasOwnProperty('lng')) {
|
||||
position.lng = this.options.lng
|
||||
}
|
||||
if (this.options.hasOwnProperty('lat')) {
|
||||
position.lat = this.options.lat
|
||||
}
|
||||
if (this.options.hasOwnProperty('alt')) {
|
||||
position.alt = this.options.alt
|
||||
}
|
||||
}
|
||||
// 如果没有高度值,则获取紧贴高度计算
|
||||
if (!position.hasOwnProperty('alt')) {
|
||||
position.alt = await this.getClampToHeight(position)
|
||||
}
|
||||
lng = this.options.customView.relativePosition.lng + position.lng
|
||||
lat = this.options.customView.relativePosition.lat + position.lat
|
||||
alt = this.options.customView.relativePosition.alt + position.alt
|
||||
destination = Cesium.Cartesian3.fromDegrees(lng, lat, alt)
|
||||
this.sdk.viewer.camera.flyTo({
|
||||
destination: destination,
|
||||
orientation: orientation
|
||||
})
|
||||
}
|
||||
else {
|
||||
let positionArray = []
|
||||
for (let i = 0; i < this.options.positions.length; i++) {
|
||||
let a = Cesium.Cartesian3.fromDegrees(this.options.positions[i].lng, this.options.positions[i].lat, this.center84.alt)
|
||||
positionArray.push(a.x, a.y, a.z)
|
||||
}
|
||||
let BoundingSphere = Cesium.BoundingSphere.fromVertices(positionArray)
|
||||
this.sdk.viewer.camera.flyToBoundingSphere(BoundingSphere, {
|
||||
offset: {
|
||||
heading: Cesium.Math.toRadians(0.0),
|
||||
pitch: Cesium.Math.toRadians(-90.0),
|
||||
roll: Cesium.Math.toRadians(0.0)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async edit(state) {
|
||||
if (state) {
|
||||
this.originalOptions = this.deepCopyObj(this.options)
|
||||
this._DialogObject = await new Dialog(this.sdk.viewer._container, {
|
||||
title: '压平面属性', left: '180px', top: '100px',
|
||||
removeCallBack: () => {
|
||||
this.Dialog.removeCallBack && this.Dialog.removeCallBack()
|
||||
},
|
||||
closeCallBack: () => {
|
||||
this.reset()
|
||||
this.Dialog.closeCallBack && this.Dialog.closeCallBack()
|
||||
}
|
||||
})
|
||||
await this._DialogObject.init()
|
||||
// 内容部分
|
||||
let contentElm = document.createElement('div');
|
||||
contentElm.innerHTML = `
|
||||
<span class="custom-divider"></span>
|
||||
<div class="div-item">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<span class="label" style="width: 56px;flex: 0 0 56px;">名称</span>
|
||||
<input class="input input-name">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<span class="label" style="width: 56px;flex: 0 0 56px;">压平高度</span>
|
||||
<div class="input-number input-number-unit-1">
|
||||
<input class="input flat-height" type="number" title="" min="-9999999" max="999999999">
|
||||
<span class="unit">m</span>
|
||||
<span class="arrow"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
this._DialogObject.contentAppChild(contentElm)
|
||||
let name_elm = contentElm.getElementsByClassName('input-name')[0]
|
||||
name_elm.value = this.options.name
|
||||
name_elm.addEventListener('input', () => {
|
||||
this.name = name_elm.value
|
||||
})
|
||||
|
||||
let height_elm = contentElm.getElementsByClassName('flat-height')[0]
|
||||
height_elm.value = this.options.height
|
||||
height_elm.addEventListener('input', () => {
|
||||
this.height = Number(height_elm.value)
|
||||
this.addFlat()
|
||||
})
|
||||
|
||||
let confirmElm = document.createElement('button');
|
||||
confirmElm.className = 'btn'
|
||||
confirmElm.innerHTML = '确认'
|
||||
this._DialogObject.footAppChild(confirmElm)
|
||||
confirmElm.addEventListener('click', () => {
|
||||
if (!this.options.name) {
|
||||
this.options.name = '压平面'
|
||||
}
|
||||
this.originalOptions = this.deepCopyObj(this.options)
|
||||
this._DialogObject.close()
|
||||
this.Dialog.confirmCallBack && this.Dialog.confirmCallBack(this.options)
|
||||
})
|
||||
|
||||
// let flatElm = document.createElement('button');
|
||||
// flatElm.className = 'btn'
|
||||
// flatElm.innerHTML = '<svg class="icon-edit"><use xlink:href="#yj-icon-edit"></use></svg>二次编辑'
|
||||
// flatElm.style.width = 'auto'
|
||||
// flatElm.style.position = 'absolute'
|
||||
// flatElm.style.left = '10px'
|
||||
// this._DialogObject.footAppChild(flatElm)
|
||||
// flatElm.addEventListener('click', () => {
|
||||
// console.log('二次编辑')
|
||||
// })
|
||||
}
|
||||
else {
|
||||
if (this._DialogObject && this._DialogObject.close) {
|
||||
this._DialogObject.close()
|
||||
this._DialogObject = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.options = this.deepCopyObj(this.originalOptions)
|
||||
this.name = this.options.name
|
||||
this.height = this.options.height
|
||||
this.addFlat()
|
||||
}
|
||||
|
||||
flatEdit(state) {
|
||||
if (state) {
|
||||
let positions = that.options.positions
|
||||
let fromDegreesArray = []
|
||||
for (let i = 0; i < positions.length; i++) {
|
||||
fromDegreesArray.push(positions[i].lng, positions[i].lat, FlatList[this.tileset.id])
|
||||
}
|
||||
that.positions = Cesium.Cartesian3.fromDegreesArrayHeights(fromDegreesArray)
|
||||
}
|
||||
}
|
||||
|
||||
flicker() { }
|
||||
|
||||
}
|
||||
|
||||
export default Flat;
|
||||
227
src/Obj/Analysis/Flat/index1.js
Normal file
227
src/Obj/Analysis/Flat/index1.js
Normal file
@ -0,0 +1,227 @@
|
||||
import Tools from "../../../Tools";
|
||||
class Flat extends Tools {
|
||||
/**
|
||||
* @constructor
|
||||
* @description 模型压平
|
||||
* @param sdk
|
||||
* @param {Cesium.Cesium3DTileset} tileset 三维模型
|
||||
* @param {Object} options
|
||||
* @param {string} attr.id id
|
||||
* @param {Number} options.height 压平高度
|
||||
* @param {Cesium.Cartesian3[]} attr.positions 压平面坐标
|
||||
*/
|
||||
constructor(sdk, tileset, options = {}) {
|
||||
super(sdk)
|
||||
if (!tileset) return;
|
||||
this.options = { ...options }
|
||||
this.options.id = options.id || this.randomString()
|
||||
this.options.positions = options.positions || []
|
||||
this.tileset = tileset;
|
||||
this.height = options.height;
|
||||
this.center = tileset.boundingSphere.center.clone();
|
||||
this.matrix = Cesium.Transforms.eastNorthUpToFixedFrame(this.center.clone());
|
||||
this.localMatrix = Cesium.Matrix4.inverse(this.matrix, new Cesium.Matrix4());
|
||||
// 多面的坐标数组
|
||||
this.regionList = [];
|
||||
// 多个面坐标转为局部模型坐标
|
||||
this.localPositionsArr = [];
|
||||
this.addRegion()
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加压平面
|
||||
* @param {Object} attr 参数
|
||||
* @param {Cesium.Cartesian3[]} attr.positions 压平面坐标
|
||||
* @param {Number} attr.height 压平深度,当前不支持单独设置
|
||||
* @param {Number} attr.id 唯一标识
|
||||
*/
|
||||
addRegion(attr) {
|
||||
// let { positions, height, id } = attr || {};
|
||||
// // this.flatHeight = height;
|
||||
// if (!id) id = (new Date()).getTime() + "" + Number(Math.random() * 1000).toFixed(0);
|
||||
// this.regionList.push(attr);
|
||||
// for (let i = 0; i < this.regionList.length; i++) {
|
||||
// let item = this.regionList[i];
|
||||
// const positions = item.positions;
|
||||
// let localCoor = this.cartesiansToLocal(positions);
|
||||
// this.localPositionsArr.push(localCoor);
|
||||
// }
|
||||
let positions = this.options.positions
|
||||
let fromDegreesArray = []
|
||||
for (let i = 0; i < positions.length; i++) {
|
||||
fromDegreesArray.push(positions[i].lng, positions[i].lat)
|
||||
}
|
||||
let localCoor = this.cartesiansToLocal(Cesium.Cartesian3.fromDegreesArray(fromDegreesArray));
|
||||
this.localPositionsArr.push(localCoor);
|
||||
|
||||
const funstr = this.getIsinPolygonFun(this.localPositionsArr);
|
||||
let str = ``;
|
||||
for (let i = 0; i < this.localPositionsArr.length; i++) {
|
||||
const coors = this.localPositionsArr[i];
|
||||
const n = coors.length;
|
||||
let instr = ``;
|
||||
coors.forEach((coordinate, index) => {
|
||||
instr += `points_${n}[${index}] = vec2(${coordinate[0]}, ${coordinate[1]});\n`;
|
||||
})
|
||||
str += `
|
||||
${instr}
|
||||
if(isPointInPolygon_${n}(position2D)){
|
||||
vec4 tileset_local_position_transformed = vec4(tileset_local_position.x, tileset_local_position.y, ground_z, 1.0);
|
||||
vec4 model_local_position_transformed = czm_inverseModel * u_tileset_localToWorldMatrix * tileset_local_position_transformed;
|
||||
vsOutput.positionMC.xy = model_local_position_transformed.xy;
|
||||
vsOutput.positionMC.z = model_local_position_transformed.z+ modelMC.z*0.002;
|
||||
return;
|
||||
}`;
|
||||
|
||||
}
|
||||
|
||||
this.updateShader(funstr, str);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据id删除压平的面
|
||||
* @param {String} id 唯一标识
|
||||
*/
|
||||
removeRegionById(id) {
|
||||
if (!id) return;
|
||||
|
||||
this.regionList = this.regionList.filter((attr) => {
|
||||
return attr.id != id;
|
||||
})
|
||||
|
||||
this.localPositionsArr = [];
|
||||
for (let i = 0; i < this.regionList.length; i++) {
|
||||
let item = this.regionList[i];
|
||||
const positions = item.positions;
|
||||
let localCoor = this.cartesiansToLocal(positions);
|
||||
this.localPositionsArr.push(localCoor);
|
||||
}
|
||||
|
||||
const funstr = this.getIsinPolygonFun(this.localPositionsArr);
|
||||
let str = ``;
|
||||
for (let i = 0; i < this.localPositionsArr.length; i++) {
|
||||
const coors = this.localPositionsArr[i];
|
||||
const n = coors.length;
|
||||
let instr = ``;
|
||||
coors.forEach((coordinate, index) => {
|
||||
instr += `points_${n}[${index}] = vec2(${coordinate[0]}, ${coordinate[1]});\n`;
|
||||
})
|
||||
str += `
|
||||
${instr}
|
||||
if(isPointInPolygon_${n}(position2D)){
|
||||
vec4 tileset_local_position_transformed = vec4(tileset_local_position.x, tileset_local_position.y, ground_z, 1.0);
|
||||
vec4 model_local_position_transformed = czm_inverseModel * u_tileset_localToWorldMatrix * tileset_local_position_transformed;
|
||||
vsOutput.positionMC.xy = model_local_position_transformed.xy;
|
||||
vsOutput.positionMC.z = model_local_position_transformed.z+ modelMC.z*0.002;
|
||||
return;
|
||||
}`;
|
||||
|
||||
}
|
||||
this.updateShader(funstr, str);
|
||||
}
|
||||
|
||||
/**
|
||||
* 销毁
|
||||
*/
|
||||
destroy() {
|
||||
this.tileset.customShader = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据数组长度,构建 判断点是否在面内 的压平函数
|
||||
*/
|
||||
getIsinPolygonFun(polygons) {
|
||||
let pmap = polygons.map((polygon) => polygon.length);
|
||||
let uniqueArray = this.getUniqueArray(pmap);
|
||||
let str = ``;
|
||||
uniqueArray.forEach(length => {
|
||||
str += `
|
||||
vec2 points_${length}[${length}];
|
||||
bool isPointInPolygon_${length}(vec2 point){
|
||||
int nCross = 0; // 交点数
|
||||
const int n = ${length};
|
||||
for(int i = 0; i < n; i++){
|
||||
vec2 p1 = points_${length}[i];
|
||||
vec2 p2 = points_${length}[int(mod(float(i+1),float(n)))];
|
||||
if(p1[1] == p2[1]){
|
||||
continue;
|
||||
}
|
||||
if(point[1] < min(p1[1], p2[1])){
|
||||
continue;
|
||||
}
|
||||
if(point[1] >= max(p1[1], p2[1])){
|
||||
continue;
|
||||
}
|
||||
float x = p1[0] + ((point[1] - p1[1]) * (p2[0] - p1[0])) / (p2[1] - p1[1]);
|
||||
if(x > point[0]){
|
||||
nCross++;
|
||||
}
|
||||
}
|
||||
return int(mod(float(nCross), float(2))) == 1;
|
||||
}
|
||||
`
|
||||
})
|
||||
return str
|
||||
}
|
||||
|
||||
updateShader(vtx1, vtx2) {
|
||||
let flatCustomShader = new Cesium.CustomShader({
|
||||
uniforms: {
|
||||
u_tileset_localToWorldMatrix: {
|
||||
type: Cesium.UniformType.MAT4,
|
||||
value: this.matrix,
|
||||
},
|
||||
u_tileset_worldToLocalMatrix: {
|
||||
type: Cesium.UniformType.MAT4,
|
||||
value: this.localMatrix,
|
||||
},
|
||||
u_flatHeight: {
|
||||
type: Cesium.UniformType.FLOAT,
|
||||
value: this.height,
|
||||
},
|
||||
},
|
||||
vertexShaderText: `
|
||||
// 所有isPointInPolygon函数
|
||||
${vtx1}
|
||||
void vertexMain(VertexInput vsInput, inout czm_modelVertexOutput vsOutput){
|
||||
vec3 modelMC = vsInput.attributes.positionMC;
|
||||
vec4 model_local_position = vec4(modelMC.x, modelMC.y, modelMC.z, 1.0);
|
||||
vec4 tileset_local_position = u_tileset_worldToLocalMatrix * czm_model * model_local_position;
|
||||
vec2 position2D = vec2(tileset_local_position.x,tileset_local_position.y);
|
||||
float ground_z = 0.0 + u_flatHeight;
|
||||
// 多个多边形区域
|
||||
${vtx2}
|
||||
}`,
|
||||
});
|
||||
this.tileset.customShader = flatCustomShader;
|
||||
this.sdk.viewer.scene.requestRender();
|
||||
}
|
||||
|
||||
// 数组去重,不能处理嵌套的数组
|
||||
getUniqueArray = (arr) => {
|
||||
return arr.filter(function (item, index, arr) {
|
||||
//当前元素,在原始数组中的第一个索引==当前索引值,否则返回当前元素
|
||||
return arr.indexOf(item, 0) === index;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// 世界坐标转数组局部坐标
|
||||
cartesiansToLocal(positions) {
|
||||
let arr = [];
|
||||
for (let i = 0; i < positions.length; i++) {
|
||||
let position = positions[i];
|
||||
let localp = Cesium.Matrix4.multiplyByPoint(
|
||||
this.localMatrix,
|
||||
position.clone(),
|
||||
new Cesium.Cartesian3()
|
||||
)
|
||||
arr.push([localp.x, localp.y]);
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
export default Flat;
|
||||
8
src/Obj/Analysis/Profile/_element.js
Normal file
8
src/Obj/Analysis/Profile/_element.js
Normal file
@ -0,0 +1,8 @@
|
||||
function html() {
|
||||
return `
|
||||
<span class="custom-divider"></span>
|
||||
<div class="profile-echarts"></div>
|
||||
`
|
||||
}
|
||||
|
||||
export { html }
|
||||
637
src/Obj/Analysis/Profile/index.js
Normal file
637
src/Obj/Analysis/Profile/index.js
Normal file
@ -0,0 +1,637 @@
|
||||
import Draw from "../../../Draw/draw";
|
||||
import MouseEvent from "../../../Event";
|
||||
import MouseTip from "../../../MouseTip";
|
||||
import Dialog from '../../../BaseDialog';
|
||||
import { html } from "./_element";
|
||||
class Profile extends Draw {
|
||||
/**
|
||||
* @constructor 剖面分析
|
||||
* @param sdk
|
||||
**/
|
||||
constructor(sdk, _Dialog = {}) {
|
||||
window.addEventListener("resize", () => {
|
||||
this.echartsObject && this.echartsObject.resize();
|
||||
});
|
||||
super(sdk)
|
||||
this.viewer = sdk.viewer;
|
||||
this.Dialog = _Dialog
|
||||
YJ.Analysis.Analyses.push(this)
|
||||
Profile.create(this)
|
||||
}
|
||||
static create(that) {
|
||||
this._currentId = Cesium.createGuid()
|
||||
let id = this._currentId
|
||||
that.clean()
|
||||
if (YJ.Measure.GetMeasureStatus()) {
|
||||
console.warn('上一次测量未结束')
|
||||
} else {
|
||||
YJ.Measure.SetMeasureStatus(true)
|
||||
that.tip = new MouseTip('左键确定,右键取消', that.sdk)
|
||||
that.event = new MouseEvent(that.sdk)
|
||||
that.positions = []
|
||||
that.points_ids = [] //存放左键点击时临时添加的point的id
|
||||
|
||||
let cache_positions = []
|
||||
let car = undefined
|
||||
that.event.mouse_left(async (movement, cartesian) => {
|
||||
try {
|
||||
if (!that.entityHasCreated) {
|
||||
Profile.create_polyline(that)
|
||||
}
|
||||
cache_positions.push(cartesian)
|
||||
that.points_ids.push(that.create_point(cartesian,))
|
||||
if (cache_positions.length == 2) {
|
||||
that.end()
|
||||
let positions = []
|
||||
cache_positions.forEach((item) => {
|
||||
positions.push(that.cartesian3Towgs84(item, that.viewer))
|
||||
})
|
||||
Profile.interPoints(that).then((points) => {
|
||||
if (this._currentId && this._currentId === id) {
|
||||
that._DialogObject ? Profile.initEcharts(that, points) : Profile.edit(that, points)
|
||||
}
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
|
||||
})
|
||||
that.event.mouse_right((movement, cartesian) => {
|
||||
let positions = []
|
||||
cache_positions = []
|
||||
that.clean()
|
||||
})
|
||||
that.event.mouse_move((movement, cartesian) => {
|
||||
that.positions = cache_positions.concat(cartesian)
|
||||
that.tip.setPosition(
|
||||
cartesian,
|
||||
movement.endPosition.x,
|
||||
movement.endPosition.y
|
||||
)
|
||||
})
|
||||
|
||||
that.event.gesture_pinck_start((movement, cartesian) => {
|
||||
let startTime = new Date()
|
||||
that.event.gesture_pinck_end(() => {
|
||||
let endTime = new Date()
|
||||
if (endTime - startTime >= 500) {
|
||||
let positions = []
|
||||
cache_positions = []
|
||||
that.end()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
static create_polyline(that) {
|
||||
that.entityHasCreated = true
|
||||
let id = that.randomString()
|
||||
that.polyline = that.viewer.entities.add(
|
||||
new Cesium.Entity({
|
||||
id: id,
|
||||
polyline: {
|
||||
positions: new Cesium.CallbackProperty(() => {
|
||||
return that.positions
|
||||
}, false),
|
||||
width: 5,
|
||||
material: Cesium.Color.fromCssColorString(that.color),
|
||||
clampToGround: true,
|
||||
zIndex: 99999999
|
||||
},
|
||||
})
|
||||
)
|
||||
return id
|
||||
}
|
||||
|
||||
/**
|
||||
* 线段插值点
|
||||
*/
|
||||
static async interPoints(that) {
|
||||
let viewer = that.viewer
|
||||
let positions = that.positions
|
||||
let positionsCartographic = []
|
||||
let positions84 = [];
|
||||
for (let index = 0; index < positions.length; index++) {
|
||||
const element = positions[index];
|
||||
let cartographic = viewer.scene.globe.ellipsoid.cartesianToCartographic(element);
|
||||
positionsCartographic.push(cartographic);
|
||||
let pos84 = that.cartesian3Towgs84(element, viewer)
|
||||
positions84.push(pos84);
|
||||
}
|
||||
let positions_Inter = [];
|
||||
let height = await that.getClampToHeight({ lng: positions84[0].lng, lat: positions84[0].lat });
|
||||
positions_Inter.push({
|
||||
position: { lng: positions84[0].lng, lat: positions84[0].lat, height: height },
|
||||
distance: 0,
|
||||
});
|
||||
for (let i = 0; i < positionsCartographic.length - 1; i++) {
|
||||
let line = turf.lineString([[positions84[i].lng, positions84[i].lat], [positions84[i + 1].lng, positions84[i + 1].lat]]);
|
||||
let totalDistance = turf.length(line, { units: 'kilometers' });
|
||||
|
||||
const m_Cartographic0 = positionsCartographic[i];
|
||||
const m_Cartographic1 = positionsCartographic[i + 1];
|
||||
let a =
|
||||
Math.abs(m_Cartographic0.longitude - m_Cartographic1.longitude) *
|
||||
10000000;
|
||||
let b =
|
||||
Math.abs(m_Cartographic0.latitude - m_Cartographic1.latitude) *
|
||||
10000000;
|
||||
//等距采样
|
||||
if (a > b) b = a;
|
||||
let length = parseInt(b / 2);
|
||||
if (length > 150) length = 150;
|
||||
if (length < 2) length = 2;
|
||||
let distance = totalDistance / (length - 1)
|
||||
for (let j = 0; j < length - 1; j++) {
|
||||
let start = j * distance
|
||||
let stop = (j + 1) * distance
|
||||
let sliced = await turf.lineSliceAlong(line, start, stop, { units: 'kilometers' });
|
||||
let lng = sliced.geometry.coordinates[sliced.geometry.coordinates.length - 1][0]
|
||||
let lat = sliced.geometry.coordinates[sliced.geometry.coordinates.length - 1][1]
|
||||
let height = await that.getClampToHeight({ lng: lng, lat: lat });
|
||||
positions_Inter.push({
|
||||
position: { lng: lng, lat: lat, height: height },
|
||||
distance: stop * 1000,
|
||||
});
|
||||
}
|
||||
}
|
||||
return positions_Inter
|
||||
}
|
||||
|
||||
static async edit(that, points) {
|
||||
if (that._DialogObject && that._DialogObject.close) {
|
||||
that._DialogObject.close()
|
||||
that._DialogObject = null
|
||||
}
|
||||
that._DialogObject = await new Dialog(that.sdk.viewer._container, {
|
||||
title: '剖面分析', left: '180px', top: '100px',
|
||||
closeCallBack: () => {
|
||||
that.clean()
|
||||
that.Dialog.closeCallBack && that.Dialog.closeCallBack()
|
||||
},
|
||||
})
|
||||
await that._DialogObject.init()
|
||||
that._DialogObject._element.body.className = that._DialogObject._element.body.className + ' profile'
|
||||
let contentElm = document.createElement('div');
|
||||
contentElm.innerHTML = html()
|
||||
that._DialogObject.contentAppChild(contentElm)
|
||||
let resetBtn = document.createElement('button');
|
||||
resetBtn.innerHTML = '<svg class="icon-edit"><use xlink:href="#yj-icon-edit"></use></svg>重新绘制'
|
||||
resetBtn.style.width = 'auto'
|
||||
resetBtn.addEventListener('click', () => {
|
||||
Profile.create(that)
|
||||
Profile.initEcharts(that)
|
||||
})
|
||||
that._DialogObject.footAppChild(resetBtn)
|
||||
Profile.initEcharts(that, points)
|
||||
}
|
||||
|
||||
static initEcharts(that, points) {
|
||||
let datas = [],
|
||||
coords = [];
|
||||
const pointsData = points;
|
||||
|
||||
let option
|
||||
if (pointsData) {
|
||||
const maxDistance = pointsData[pointsData.length - 1].distance;
|
||||
let xAixMax = Math.ceil(maxDistance);
|
||||
for (let index = 0; index < pointsData.length; index++) {
|
||||
const element = pointsData[index];
|
||||
if (element.position.height === void 0) {
|
||||
continue
|
||||
}
|
||||
const curData = [
|
||||
element.distance.toFixed(2),
|
||||
element.position.height.toFixed(2),
|
||||
];
|
||||
datas.push(curData);
|
||||
const curCoords = [element.position.lng, element.position.lat];
|
||||
coords.push(curCoords);
|
||||
}
|
||||
const pointOption = {
|
||||
show: true,
|
||||
pixelSize: 10,
|
||||
color: Cesium.Color.GREEN,
|
||||
outlineColor: Cesium.Color.SKYBLUE,
|
||||
outlineWidth: 3,
|
||||
disableDepthTestDistance: Number.POSITIVE_INFINITY
|
||||
};
|
||||
const ele = that._DialogObject._element.content.getElementsByClassName("profile-echarts")[0];
|
||||
that.echartsObject = echarts.init(ele);
|
||||
option = {
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
textStyle: {
|
||||
align: "left",
|
||||
},
|
||||
formatter(params) {
|
||||
const xy = coords[params[0].dataIndex];
|
||||
const tipData = params[0]["data"];
|
||||
if (!that.tipEntity) {
|
||||
that.tipEntity = that.sdk.viewer.entities.add({
|
||||
position: Cesium.Cartesian3.fromDegrees(
|
||||
xy[0],
|
||||
xy[1],
|
||||
Number(tipData[1])
|
||||
),
|
||||
point: pointOption,
|
||||
});
|
||||
} else {
|
||||
that.tipEntity.position = Cesium.Cartesian3.fromDegrees(
|
||||
xy[0],
|
||||
xy[1],
|
||||
Number(tipData[1])
|
||||
);
|
||||
}
|
||||
return (
|
||||
"距离:" +
|
||||
tipData[0] +
|
||||
"m<br>" +
|
||||
"高度:" +
|
||||
tipData[1] +
|
||||
"m<br>" +
|
||||
"坐标:" +
|
||||
xy[0].toFixed(5) +
|
||||
"," +
|
||||
xy[1].toFixed(5)
|
||||
);
|
||||
},
|
||||
},
|
||||
grid: {
|
||||
top: 40,
|
||||
bottom: 20,
|
||||
left: 55,
|
||||
right: 30
|
||||
},
|
||||
calculable: true,
|
||||
xAxis: [
|
||||
{
|
||||
type: "value",
|
||||
max: xAixMax,
|
||||
scale: true,
|
||||
axisLabel: {
|
||||
color: '#ffffff'
|
||||
},
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: "#ffffff"
|
||||
}
|
||||
}
|
||||
},
|
||||
],
|
||||
yAxis: [
|
||||
{
|
||||
type: "value",
|
||||
scale: true,
|
||||
axisLabel: {
|
||||
color: '#ffffff'
|
||||
},
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: "#ffffff"
|
||||
}
|
||||
}
|
||||
},
|
||||
],
|
||||
series: [
|
||||
{
|
||||
name: "ProfileLine",
|
||||
type: "line",
|
||||
data: datas,
|
||||
smooth: true,
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: "#39FDA1",
|
||||
},
|
||||
},
|
||||
lineStyle: {
|
||||
normal: {
|
||||
width: 3,
|
||||
color: {
|
||||
type: "linear",
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 1,
|
||||
y2: 0,
|
||||
colorStops: [
|
||||
{
|
||||
offset: 0,
|
||||
color: "rgba(85,254,139,1)", // 0% 处的颜色
|
||||
},
|
||||
{
|
||||
offset: 0.5,
|
||||
color: "rgba(7,252,202,1)", // 100% 处的颜色
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: "rgba(14,245,210,1)", // 100% 处的颜色
|
||||
},
|
||||
],
|
||||
globalCoord: false, // 缺省为 false
|
||||
},
|
||||
},
|
||||
},
|
||||
areaStyle: {
|
||||
normal: {
|
||||
color: new echarts.graphic.LinearGradient(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
[
|
||||
{
|
||||
offset: 0,
|
||||
color: "rgba(102,153,255,1)",
|
||||
},
|
||||
{
|
||||
offset: 0.8,
|
||||
color: "rgba(102,153,255,0.08)",
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: "rgba(9,173,208,0.15)",
|
||||
},
|
||||
],
|
||||
false
|
||||
),
|
||||
shadowColor: "rgba(14,245,210,1)", //阴影颜色
|
||||
shadowBlur: 20,
|
||||
},
|
||||
},
|
||||
markPoint: {
|
||||
data: [
|
||||
{
|
||||
type: "max",
|
||||
name: "最高点",
|
||||
label: {
|
||||
color: '#ffffff',
|
||||
}
|
||||
},
|
||||
{
|
||||
type: "min",
|
||||
name: "最低点",
|
||||
label: {
|
||||
color: '#ffffff',
|
||||
}
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
else {
|
||||
const ele = that._DialogObject._element.content.getElementsByClassName("profile-echarts")[0];
|
||||
that.echartsObject = echarts.init(ele);
|
||||
option = {
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
textStyle: {
|
||||
align: "left",
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
top: 40,
|
||||
bottom: 20,
|
||||
left: 55,
|
||||
right: 30
|
||||
},
|
||||
calculable: true,
|
||||
xAxis: [
|
||||
{
|
||||
type: "value",
|
||||
scale: true,
|
||||
axisLabel: {
|
||||
color: '#ffffff'
|
||||
},
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: "#ffffff"
|
||||
}
|
||||
}
|
||||
},
|
||||
],
|
||||
yAxis: [
|
||||
{
|
||||
type: "value",
|
||||
scale: true,
|
||||
axisLabel: {
|
||||
color: '#ffffff'
|
||||
},
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: "#ffffff"
|
||||
}
|
||||
}
|
||||
},
|
||||
],
|
||||
series: [
|
||||
{
|
||||
name: "ProfileLine",
|
||||
type: "line",
|
||||
data: [],
|
||||
smooth: true,
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: "#39FDA1",
|
||||
},
|
||||
},
|
||||
lineStyle: {
|
||||
normal: {
|
||||
width: 3,
|
||||
color: {
|
||||
type: "linear",
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 1,
|
||||
y2: 0,
|
||||
colorStops: [
|
||||
{
|
||||
offset: 0,
|
||||
color: "rgba(85,254,139,1)", // 0% 处的颜色
|
||||
},
|
||||
{
|
||||
offset: 0.5,
|
||||
color: "rgba(7,252,202,1)", // 100% 处的颜色
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: "rgba(14,245,210,1)", // 100% 处的颜色
|
||||
},
|
||||
],
|
||||
globalCoord: false, // 缺省为 false
|
||||
},
|
||||
},
|
||||
},
|
||||
areaStyle: {
|
||||
normal: {
|
||||
color: new echarts.graphic.LinearGradient(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
[
|
||||
{
|
||||
offset: 0,
|
||||
color: "rgba(102,153,255,1)",
|
||||
},
|
||||
{
|
||||
offset: 0.8,
|
||||
color: "rgba(102,153,255,0.08)",
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: "rgba(9,173,208,0.15)",
|
||||
},
|
||||
],
|
||||
false
|
||||
),
|
||||
shadowColor: "rgba(14,245,210,1)", //阴影颜色
|
||||
shadowBlur: 20,
|
||||
},
|
||||
},
|
||||
markPoint: {
|
||||
data: [
|
||||
{
|
||||
type: "max",
|
||||
name: "最高点",
|
||||
label: {
|
||||
color: '#ffffff',
|
||||
}
|
||||
},
|
||||
{
|
||||
type: "min",
|
||||
name: "最低点",
|
||||
label: {
|
||||
color: '#ffffff',
|
||||
}
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
that.echartsObject.setOption(option);
|
||||
}
|
||||
|
||||
clean() {
|
||||
this.end()
|
||||
this._currentId = null
|
||||
this.entityHasCreated = false
|
||||
this.polyline && this.viewer.entities.remove(this.polyline)
|
||||
this.tipEntity && this.viewer.entities.remove(this.tipEntity)
|
||||
this.polyline = null
|
||||
this.tipEntity = null
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.clean()
|
||||
if (this._DialogObject && this._DialogObject.close) {
|
||||
this._DialogObject.close()
|
||||
this._DialogObject = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// const Profile = function (viewer, callback) {
|
||||
// if (!viewer) throw new Error("no viewer object!");
|
||||
// if (window.profileEntities && window.profileEntities.length > 0) {
|
||||
// window.profileEntities.forEach((element) => {
|
||||
// window.viewer.entities.remove(element);
|
||||
// });
|
||||
// }
|
||||
// window.profileEntities = [];
|
||||
// CreatePolyline(
|
||||
// viewer,
|
||||
// window.profileEntities,
|
||||
// { color: Cesium.Color.RED, width: 2 },
|
||||
// function (e) {
|
||||
// e.polyline.clampToGround = true;
|
||||
// console.log(e.pottingPoint);
|
||||
// let points = interPoints(viewer, e.pottingPoint, [e]);
|
||||
// console.log(points);
|
||||
// if (typeof callback == "function") callback(points);
|
||||
// }
|
||||
// );
|
||||
// };
|
||||
// /**
|
||||
// * 线段插值点
|
||||
// * @param {*} viewer
|
||||
// * @param {*} positions 线段节点集合
|
||||
// * @param {*} objectsToExclude 高度采集时排除的对象集合
|
||||
// * @returns 经纬度点集合,包含距离值
|
||||
// */
|
||||
// function interPoints(viewer, positions, objectsToExclude) {
|
||||
// let positionsCartographic = [];
|
||||
// let terrainSamplePositions = [];
|
||||
// for (let index = 0; index < positions.length; index++) {
|
||||
// const element = positions[index];
|
||||
// let ellipsoid = viewer.scene.globe.ellipsoid;
|
||||
// let cartographic = ellipsoid.cartesianToCartographic(element);
|
||||
// positionsCartographic.push(cartographic);
|
||||
// }
|
||||
// for (let i = 0; i < positionsCartographic.length; i++) {
|
||||
// const m_Cartographic0 = positionsCartographic[i];
|
||||
// const m_Cartographic1 = positionsCartographic[i + 1];
|
||||
// if (m_Cartographic1) {
|
||||
// let a =
|
||||
// Math.abs(m_Cartographic0.longitude - m_Cartographic1.longitude) *
|
||||
// 10000000;
|
||||
// let b =
|
||||
// Math.abs(m_Cartographic0.latitude - m_Cartographic1.latitude) *
|
||||
// 10000000;
|
||||
// //等距采样
|
||||
// if (a > b) b = a;
|
||||
// let length = parseInt(b / 2);
|
||||
// if (length > 1000) length = 1000;
|
||||
// if (length < 2) length = 2;
|
||||
// for (let j = 0; j < length; j++) {
|
||||
// terrainSamplePositions.push(
|
||||
// new Cesium.Cartographic(
|
||||
// Cesium.Math.lerp(
|
||||
// m_Cartographic0.longitude,
|
||||
// m_Cartographic1.longitude,
|
||||
// j / (length - 1)
|
||||
// ),
|
||||
// Cesium.Math.lerp(
|
||||
// m_Cartographic0.latitude,
|
||||
// m_Cartographic1.latitude,
|
||||
// j / (length - 1)
|
||||
// )
|
||||
// )
|
||||
// );
|
||||
// }
|
||||
// terrainSamplePositions.pop();
|
||||
// } else {
|
||||
// terrainSamplePositions.push(m_Cartographic0);
|
||||
// }
|
||||
// }
|
||||
// let positions_Inter = [];
|
||||
// let distance = 0;
|
||||
// for (let n = 0; n < terrainSamplePositions.length; n++) {
|
||||
// //地理坐标(弧度)转经纬度坐标
|
||||
// let curCartographic = terrainSamplePositions[n];
|
||||
// let height = viewer.scene.sampleHeight(curCartographic, objectsToExclude);
|
||||
// const lon = (curCartographic.longitude / Math.PI) * 180;
|
||||
// const lat = (curCartographic.latitude / Math.PI) * 180;
|
||||
// let point = Cesium.Cartesian3.fromDegrees(lon, lat, height);
|
||||
// let preCartographic = terrainSamplePositions[n - 1];
|
||||
// if (preCartographic) {
|
||||
// const lon1 = (preCartographic.longitude / Math.PI) * 180;
|
||||
// const lat1 = (preCartographic.latitude / Math.PI) * 180;
|
||||
// let point1 = Cesium.Cartesian3.fromDegrees(lon1, lat1, height);
|
||||
// let curDis = Cesium.Cartesian3.distance(point1, point);
|
||||
// distance += curDis;
|
||||
// }
|
||||
// positions_Inter.push({
|
||||
// position: { lon: lon, lat: lat, height: height },
|
||||
// distance: distance,
|
||||
// });
|
||||
// }
|
||||
// return positions_Inter;
|
||||
// }
|
||||
export default Profile;
|
||||
145
src/Obj/Analysis/Section/index.js
Normal file
145
src/Obj/Analysis/Section/index.js
Normal file
@ -0,0 +1,145 @@
|
||||
import Tools from "../../../Tools";
|
||||
class Section extends Tools {
|
||||
/**
|
||||
* @constructor 剖切
|
||||
* @param sdk
|
||||
* @param tiles3d {object} 3dtiles对象
|
||||
* @param {Array.<object>} options.positions 经纬度[{lon,lat,alt},...]
|
||||
* @param options.regionsType=false 裁剪类型 false:裁剪内部,true:裁剪外部
|
||||
* **/
|
||||
constructor(sdk, tiles3d, options = {}) {
|
||||
|
||||
|
||||
super(sdk, options)
|
||||
this.viewer = sdk.viewer
|
||||
this.tiles3d = tiles3d
|
||||
this.options = { ...options }
|
||||
this.options.regionsType = this.options.regionsType || false
|
||||
// YJ.Analysis.Analyses.push(this)
|
||||
this.Planes = []
|
||||
Section.start(this)
|
||||
}
|
||||
|
||||
get regionsType() {
|
||||
return this.options.regionsType
|
||||
}
|
||||
set regionsType(v) {
|
||||
this.options.regionsType = v
|
||||
if (this.Planes.length > 0) {
|
||||
this.Planes = []
|
||||
Section.planeCollection(this)
|
||||
}
|
||||
}
|
||||
|
||||
static start(that) {
|
||||
let positions = that.options.positions || []
|
||||
if(!that.isConvex(positions)) {
|
||||
window.ELEMENT && window.ELEMENT.Message({
|
||||
message: '不支持凹多边形',
|
||||
type: 'warning',
|
||||
duration: 1500
|
||||
});
|
||||
console.log('不支持凹多边形')
|
||||
return
|
||||
}
|
||||
that.inverseTransform = getInverseTransform(that.tiles3d)
|
||||
that.Planes = []
|
||||
let array = []
|
||||
if (positions.length > 0) {
|
||||
for (let i = 0; i < positions.length; i++) {
|
||||
array.push([positions[i].lng, positions[i].lat])
|
||||
}
|
||||
array.push([positions[0].lng, positions[0].lat])
|
||||
that.isClockwise = turf.booleanClockwise(turf.lineString(array));
|
||||
}
|
||||
Section.planeCollection(that)
|
||||
|
||||
function getInverseTransform(tileSet) {
|
||||
let transform
|
||||
const tmp = tileSet.root.transform
|
||||
if ((tmp && tmp.equals(Cesium.Matrix4.IDENTITY)) || !tmp) {
|
||||
transform = Cesium.Transforms.eastNorthUpToFixedFrame(tileSet.boundingSphere.center)
|
||||
} else {
|
||||
transform = Cesium.Matrix4.fromArray(tileSet.root.transform)
|
||||
}
|
||||
return Cesium.Matrix4.inverseTransformation(transform, new Cesium.Matrix4())
|
||||
}
|
||||
}
|
||||
|
||||
static planeCollection(that) {
|
||||
let positions = that.options.positions || []
|
||||
if (that.regionsType == that.isClockwise) {
|
||||
for (let i = 0; i < positions.length; i++) {
|
||||
if (i === (positions.length - 1)) {
|
||||
that.Planes.push(createPlane(positions[i], positions[0], that.inverseTransform))
|
||||
} else {
|
||||
that.Planes.push(createPlane(positions[i], positions[i + 1], that.inverseTransform))
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (let i = positions.length - 1; i >= 0; i--) {
|
||||
if (i === 0) {
|
||||
that.Planes.push(createPlane(positions[i], positions[positions.length - 1], that.inverseTransform))
|
||||
} else {
|
||||
that.Planes.push(createPlane(positions[i], positions[i - 1], that.inverseTransform))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(that.tiles3d.clippingPlanes) {
|
||||
that.tiles3d.clippingPlanes.removeAll()
|
||||
for(let i=0;i<that.Planes.length;i++) {
|
||||
that.tiles3d.clippingPlanes.add(that.Planes[i])
|
||||
}
|
||||
that.tiles3d.clippingPlanes.enabled = true
|
||||
|
||||
}
|
||||
else {
|
||||
const PlaneCollection = new Cesium.ClippingPlaneCollection({
|
||||
planes: that.Planes,
|
||||
enabled: true,
|
||||
unionClippingRegions: that.regionsType,
|
||||
edgeColor: Cesium.Color.WHITE,
|
||||
edgeWidth: 1,
|
||||
})
|
||||
that.tiles3d.clippingPlanes = PlaneCollection
|
||||
}
|
||||
|
||||
function createPlane(p1, p2, inverseTransform) {
|
||||
// 将仅包含经纬度信息的p1,p2,转换为相应坐标系的cartesian3对象
|
||||
const p1C3 = getOriginCoordinateSystemPoint(p1, inverseTransform)
|
||||
const p2C3 = getOriginCoordinateSystemPoint(p2, inverseTransform)
|
||||
|
||||
// 定义一个垂直向上的向量up
|
||||
const up = new Cesium.Cartesian3(0, 0, 10)
|
||||
// right 实际上就是由p1指向p2的向量
|
||||
const right = Cesium.Cartesian3.subtract(p2C3, p1C3, new Cesium.Cartesian3())
|
||||
|
||||
// 计算normal, right叉乘up,得到平面法向量,这个法向量指向right的右侧
|
||||
let normal = Cesium.Cartesian3.cross(right, up, new Cesium.Cartesian3())
|
||||
normal = Cesium.Cartesian3.normalize(normal, normal)
|
||||
|
||||
// 由于已经获得了法向量和过平面的一点,因此可以直接构造Plane,并进一步构造ClippingPlane
|
||||
const planeTmp = Cesium.Plane.fromPointNormal(p1C3, normal)
|
||||
return Cesium.ClippingPlane.fromPlane(planeTmp)
|
||||
}
|
||||
|
||||
function getOriginCoordinateSystemPoint(point, inverseTransform) {
|
||||
const val = Cesium.Cartesian3.fromDegrees(point.lng, point.lat)
|
||||
return Cesium.Matrix4.multiplyByPoint(
|
||||
inverseTransform, val, new Cesium.Cartesian3(0, 0, 0))
|
||||
}
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.Planes = []
|
||||
// this.tiles3d.clippingPlanes = new Cesium.ClippingPlaneCollection()
|
||||
if(this.tiles3d.clippingPlanes) {
|
||||
this.tiles3d.clippingPlanes.enabled = false
|
||||
this.tiles3d.clippingPlanes.removeAll()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Section;
|
||||
517
src/Obj/Analysis/SlopeAspect/index.js
Normal file
517
src/Obj/Analysis/SlopeAspect/index.js
Normal file
@ -0,0 +1,517 @@
|
||||
|
||||
import Tools from "../../../Tools";
|
||||
import DrawPolygon from "../../../Draw/drawPolygon"
|
||||
import MouseEvent from '../../../Event/index'
|
||||
class SlopeAspect extends Tools {
|
||||
/**
|
||||
* @constructor 坡度坡向分析
|
||||
* @param sdk
|
||||
* **/
|
||||
constructor(sdk) {
|
||||
super(sdk)
|
||||
this.viewer = sdk.viewer;
|
||||
let terrainAvailability = this.viewer.terrainProvider.availability;
|
||||
if (!terrainAvailability) {
|
||||
this.error = '未加载地形数据!'
|
||||
window.ELEMENT && window.ELEMENT.Message({
|
||||
message: '未加载地形数据!',
|
||||
type: 'warning',
|
||||
duration: 1500
|
||||
});
|
||||
return
|
||||
}
|
||||
this.event
|
||||
this.result = []; //存储创建的坡度分析结果,primitive集合
|
||||
this.handler = undefined;
|
||||
this.toolTip = "";
|
||||
YJ.Analysis.Analyses.push(this)
|
||||
this.Draw = new DrawPolygon(this.sdk)
|
||||
// this.createNew4Distance()
|
||||
this.createNew4Num(50)
|
||||
}
|
||||
|
||||
//等距离切分网格
|
||||
createNew4Distance(distance) {
|
||||
distance = distance || 0.1; //默认0.1km精度
|
||||
let width = distance * 200 > 35 ? 35 : distance * 200;
|
||||
this.arrowWidth = width < 15 ? 15 : width;
|
||||
const $this = this;
|
||||
const viewer = this.viewer;
|
||||
this.Draw.start((e, positions) => {
|
||||
if (!positions || positions.length <= 2) {
|
||||
window.ELEMENT && window.ELEMENT.Message({
|
||||
message: '至少拥有三个坐标位置!',
|
||||
type: 'warning',
|
||||
duration: 1500
|
||||
});
|
||||
return
|
||||
}
|
||||
let boundary = [];
|
||||
let minX = 10000,
|
||||
minY = 10000,
|
||||
maxX = -10000,
|
||||
maxY = -1000;
|
||||
for (let index = 0; index < positions.length; index++) {
|
||||
const element = positions[index];
|
||||
const x = element.lng;
|
||||
const y = element.lat;
|
||||
boundary.push([x, y]);
|
||||
minX = x < minX ? x : minX;
|
||||
minY = y < minY ? y : minY;
|
||||
maxX = x > maxX ? x : maxX;
|
||||
maxY = y > maxY ? y : maxY;
|
||||
}
|
||||
boundary.push(boundary[0]);
|
||||
let bbox = [minX, minY, maxX, maxY];
|
||||
let mask = turf.polygon([boundary]);
|
||||
let gridSquare = turf.squareGrid(bbox, distance, { mask: mask });
|
||||
this.createEllipse(gridSquare);
|
||||
})
|
||||
}
|
||||
// 等分切分网格,切分成一个num*num的网格
|
||||
createNew4Num(n) {
|
||||
let num = n
|
||||
this.Draw.start((e, positions) => {
|
||||
if (!positions || positions.length <= 2) {
|
||||
console.warn('至少拥有三个坐标位置!')
|
||||
return
|
||||
}
|
||||
let boundary = [];
|
||||
let minX = 10000,
|
||||
minY = 10000,
|
||||
maxX = -10000,
|
||||
maxY = -1000;
|
||||
for (let index = 0; index < positions.length; index++) {
|
||||
const element = positions[index];
|
||||
const x = element.lng;
|
||||
const y = element.lat;
|
||||
boundary.push([x, y]);
|
||||
minX = x < minX ? x : minX;
|
||||
minY = y < minY ? y : minY;
|
||||
maxX = x > maxX ? x : maxX;
|
||||
maxY = y > maxY ? y : maxY;
|
||||
}
|
||||
boundary.push(boundary[0]);
|
||||
let bbox = [minX, minY, maxX, maxY];
|
||||
let a = maxX - minX;
|
||||
let b = maxY - minY;
|
||||
b = b > a ? b : a;
|
||||
|
||||
// 根据面积修改网格数
|
||||
let mask = turf.polygon([boundary]);
|
||||
let area = turf.area(mask);
|
||||
if (area > 5000000000000) {
|
||||
num = num - 25;
|
||||
}
|
||||
else if (area > 1000000000000) {
|
||||
num = num - 20;
|
||||
}
|
||||
else if (area > 500000000000) {
|
||||
num = num - 15;
|
||||
}
|
||||
else if (area > 100000000000) {
|
||||
num = num - 10;
|
||||
}
|
||||
else if (area > 60000000000) {
|
||||
num = num - 5;
|
||||
}
|
||||
|
||||
const step = b / num;
|
||||
let width = step * 2000 > 35 ? 35 : step * 2000;
|
||||
this.arrowWidth = width < 15 ? 15 : width;
|
||||
|
||||
let gridSquare = turf.squareGrid(bbox, step, {
|
||||
units: "degrees",
|
||||
mask: mask,
|
||||
});
|
||||
this.createEllipse(gridSquare);
|
||||
})
|
||||
// CreatePolygonOnGround(
|
||||
// viewer,
|
||||
// [],
|
||||
// {
|
||||
// color: Cesium.Color.RED.withAlpha(0.1),
|
||||
// outlineColor: Cesium.Color.YELLOW,
|
||||
// outlineWidth: 2,
|
||||
// },
|
||||
// function (polygon) {
|
||||
// let degrees = $this.Cartesian3ListToWGS84(polygon.pottingPoint);
|
||||
// viewer.entities.remove(polygon);
|
||||
// let boundary = [];
|
||||
// let minX = 10000,
|
||||
// minY = 10000,
|
||||
// maxX = -10000,
|
||||
// maxY = -1000;
|
||||
// for (let index = 0; index < degrees.length; index++) {
|
||||
// const element = degrees[index];
|
||||
// const x = element.lng;
|
||||
// const y = element.lat;
|
||||
// boundary.push([x, y]);
|
||||
// minX = x < minX ? x : minX;
|
||||
// minY = y < minY ? y : minY;
|
||||
// maxX = x > maxX ? x : maxX;
|
||||
// maxY = y > maxY ? y : maxY;
|
||||
// }
|
||||
// boundary.push(boundary[0]);
|
||||
// let bbox = [minX, minY, maxX, maxY];
|
||||
// let a = maxX - minX;
|
||||
// let b = maxY - minY;
|
||||
// b = b > a ? b : a;
|
||||
// const step = b / num;
|
||||
// let width = step * 2000 > 35 ? 35 : step * 2000;
|
||||
// this.arrowWidth = width < 15 ? 15 : width;
|
||||
// let mask = turf.polygon([boundary]);
|
||||
// let gridSquare = turf.squareGrid(bbox, step, {
|
||||
// units: "degrees",
|
||||
// mask: mask,
|
||||
// });
|
||||
// this.createEllipse(gridSquare);
|
||||
// }
|
||||
// );
|
||||
}
|
||||
createEllipse(gridSquare) {
|
||||
let boxResults = [];
|
||||
for (let index = 0; index < gridSquare.features.length; index++) {
|
||||
const feature = gridSquare.features[index];
|
||||
const coordinates = feature.geometry.coordinates[0];
|
||||
const centerdegree = [
|
||||
(coordinates[0][0] + coordinates[2][0]) / 2,
|
||||
(coordinates[0][1] + coordinates[2][1]) / 2,
|
||||
];
|
||||
let centerCartographic = Cesium.Cartographic.fromDegrees(
|
||||
centerdegree[0],
|
||||
centerdegree[1]
|
||||
);
|
||||
boxResults.push(centerCartographic);
|
||||
for (let i = 0; i < coordinates.length; i++) {
|
||||
const coord = coordinates[i];
|
||||
let cartographic = Cesium.Cartographic.fromDegrees(coord[0], coord[1]);
|
||||
boxResults.push(cartographic);
|
||||
const coord1 = coordinates[i + 1];
|
||||
if (coord1) {
|
||||
let newCoord = [
|
||||
(coord[0] + coord1[0]) / 2,
|
||||
(coord[1] + coord1[1]) / 2,
|
||||
];
|
||||
let newCartographic = Cesium.Cartographic.fromDegrees(
|
||||
newCoord[0],
|
||||
newCoord[1]
|
||||
);
|
||||
boxResults.push(newCartographic);
|
||||
}
|
||||
}
|
||||
}
|
||||
let _this = this
|
||||
// 点位过多,分为三份计算
|
||||
let num = (Math.floor(boxResults.length / 3) + '')
|
||||
num = Number(num.substring(0, num.length - 1))*10
|
||||
let i=0
|
||||
let points = boxResults.slice(i * num, (i + 1) * num)
|
||||
if (points.length > 0) {
|
||||
sampleTerrainMostDetailed(points)
|
||||
}
|
||||
function sampleTerrainMostDetailed(ps) {
|
||||
Cesium.sampleTerrainMostDetailed(
|
||||
_this.viewer.scene.terrainProvider,
|
||||
ps
|
||||
).then((updatePositions) => {
|
||||
i++
|
||||
let points = boxResults.slice(i * num, (i + 1) * num)
|
||||
if (points.length > 0) {
|
||||
sampleTerrainMostDetailed(points)
|
||||
}
|
||||
let arrr = [];
|
||||
let ellipseResults = updatePositions.reduce(function (
|
||||
pre,
|
||||
item,
|
||||
index,
|
||||
updatePositions
|
||||
) {
|
||||
var begin = index * 10;
|
||||
var end = begin + 10;
|
||||
var res = updatePositions.slice(begin, end);
|
||||
if (res.length != 0) {
|
||||
arrr[index] = res;
|
||||
}
|
||||
return arrr;
|
||||
},
|
||||
[]);
|
||||
_this.calculateSlope(ellipseResults);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
createPolygonInsrance(points, color, curSlope) {
|
||||
let positions = [];
|
||||
for (let index = 1; index < points.length - 1; index++) {
|
||||
const element = points[index];
|
||||
positions.push(Cesium.Cartographic.toCartesian(element));
|
||||
}
|
||||
let polygon = new Cesium.PolygonGeometry({
|
||||
polygonHierarchy: new Cesium.PolygonHierarchy(positions),
|
||||
});
|
||||
|
||||
let polygonInstance = new Cesium.GeometryInstance({
|
||||
id: {
|
||||
type: "SlopeAspect",
|
||||
value: curSlope
|
||||
},
|
||||
geometry: polygon,
|
||||
attributes: {
|
||||
color: Cesium.ColorGeometryInstanceAttribute.fromColor(
|
||||
Cesium.Color.fromCssColorString(color)
|
||||
),
|
||||
show: new Cesium.ShowGeometryInstanceAttribute(true), //显示或者隐藏
|
||||
},
|
||||
});
|
||||
return polygonInstance;
|
||||
}
|
||||
createArrowInstance(
|
||||
targetPoint,
|
||||
center,
|
||||
diagonalPoint,
|
||||
heightDifference,
|
||||
curSlope
|
||||
) {
|
||||
let cartographic_0 = new Cesium.Cartographic(
|
||||
(targetPoint.longitude + center.longitude) / 2,
|
||||
(targetPoint.latitude + center.latitude) / 2,
|
||||
(targetPoint.height + center.height) / 2
|
||||
);
|
||||
let cartographic_1 = new Cesium.Cartographic(
|
||||
(diagonalPoint.longitude + center.longitude) / 2,
|
||||
(diagonalPoint.latitude + center.latitude) / 2,
|
||||
(diagonalPoint.height + center.height) / 2
|
||||
);
|
||||
//偏移的
|
||||
let positions1 =
|
||||
heightDifference > 0
|
||||
? [
|
||||
Cesium.Cartographic.toCartesian(cartographic_0),
|
||||
Cesium.Cartographic.toCartesian(cartographic_1),
|
||||
]
|
||||
: [
|
||||
Cesium.Cartographic.toCartesian(cartographic_1),
|
||||
Cesium.Cartographic.toCartesian(cartographic_0),
|
||||
];
|
||||
//箭头线
|
||||
const instance = new Cesium.GeometryInstance({
|
||||
id: {
|
||||
type: "SlopeAspect",
|
||||
value: curSlope,
|
||||
},
|
||||
geometry: new Cesium.GroundPolylineGeometry({
|
||||
positions: positions1,
|
||||
width: this.arrowWidth,
|
||||
}),
|
||||
attributes: {
|
||||
color: Cesium.ColorGeometryInstanceAttribute.fromColor(
|
||||
Cesium.Color.BLUE.withAlpha(0.6)
|
||||
),
|
||||
show: new Cesium.ShowGeometryInstanceAttribute(true), //显示或者隐藏
|
||||
},
|
||||
});
|
||||
return instance;
|
||||
}
|
||||
calculateSlope(ellipseResults) {
|
||||
let instances = [];
|
||||
let polygonInstance = [];
|
||||
for (let index = 0; index < ellipseResults.length; index++) {
|
||||
const ellipse = ellipseResults[index];
|
||||
|
||||
const center = ellipse[0];
|
||||
let heightDifference = 0;
|
||||
let maxIndex = 0;
|
||||
for (let i = 1; i < ellipse.length - 1; i++) {
|
||||
const point = ellipse[i];
|
||||
let curHD = point.height - center.height;
|
||||
if (Math.abs(curHD) > heightDifference) {
|
||||
heightDifference = curHD;
|
||||
maxIndex = i;
|
||||
}
|
||||
}
|
||||
let pos0 = new Cesium.Cartographic(center.longitude, center.latitude, 0);
|
||||
let pos1 = new Cesium.Cartographic(
|
||||
ellipse[maxIndex].longitude,
|
||||
ellipse[maxIndex].latitude,
|
||||
0
|
||||
);
|
||||
let distance = Cesium.Cartesian3.distance(
|
||||
Cesium.Cartographic.toCartesian(pos0),
|
||||
Cesium.Cartographic.toCartesian(pos1)
|
||||
);
|
||||
let curSlope = Math.abs(heightDifference / distance); //坡度的tan值
|
||||
let curColor = this.calculateSlopeColor(curSlope, 0.4);
|
||||
const curPolygonInstance = this.createPolygonInsrance(ellipse, curColor, curSlope);
|
||||
polygonInstance.push(curPolygonInstance);
|
||||
|
||||
let diagonalPoint =
|
||||
maxIndex > 4 ? ellipse[maxIndex - 4] : ellipse[maxIndex + 4]; //对角点
|
||||
let targetPoint = ellipse[maxIndex];
|
||||
const arrowInstance = this.createArrowInstance(
|
||||
targetPoint,
|
||||
center,
|
||||
diagonalPoint,
|
||||
heightDifference,
|
||||
curSlope
|
||||
);
|
||||
instances.push(arrowInstance);
|
||||
}
|
||||
const mapPrimitive = this.viewer.scene.primitives.add(
|
||||
new Cesium.GroundPrimitive({
|
||||
geometryInstances: polygonInstance,
|
||||
appearance: new Cesium.PerInstanceColorAppearance({
|
||||
translucent: true, //false时透明度无效
|
||||
closed: false,
|
||||
}),
|
||||
})
|
||||
);
|
||||
const arrowPrimitive = this.viewer.scene.primitives.add(
|
||||
new Cesium.GroundPolylinePrimitive({
|
||||
geometryInstances: instances,
|
||||
appearance: new Cesium.PolylineMaterialAppearance({
|
||||
material: new Cesium.Material({
|
||||
fabric: {
|
||||
type: "PolylineArrow",
|
||||
uniforms: {
|
||||
color: new Cesium.Color(1.0, 1.0, 0.0, 0.8),
|
||||
},
|
||||
},
|
||||
}),
|
||||
}),
|
||||
})
|
||||
);
|
||||
this.result.push(arrowPrimitive, mapPrimitive);
|
||||
|
||||
this.event = new MouseEvent(this.sdk)
|
||||
let mouseEvent = (movement, cartesian) => {
|
||||
// console.log(movement, cartesian)
|
||||
let infoBox = document.getElementById('SlopeAspect-box')
|
||||
if (!infoBox) {
|
||||
infoBox = document.createElement('div')
|
||||
infoBox.id = 'SlopeAspect-box'
|
||||
infoBox.style.pointerEvents = 'none'
|
||||
infoBox.style.display = 'none'
|
||||
infoBox.style.position = 'absolute'
|
||||
infoBox.style.background = '#333333'
|
||||
infoBox.style.color = '#fff'
|
||||
infoBox.style.color = '#fff'
|
||||
infoBox.style.padding = '5px'
|
||||
infoBox.style.fontSize = '12px'
|
||||
infoBox.style.borderRadius = '5px'
|
||||
infoBox.style.transform = 'translate(-50%, -10px)'
|
||||
infoBox.innerHTML = `
|
||||
<div class="value">坡度:</div>
|
||||
<span style="
|
||||
position: absolute;
|
||||
border: 4px solid;
|
||||
border-color: #fff0 #fff0 #333333 #333333;
|
||||
transform: rotate(-45deg);
|
||||
left: calc(50% - 5px);
|
||||
"></span>
|
||||
`
|
||||
document.body.appendChild(infoBox)
|
||||
}
|
||||
let vlaElm = infoBox.getElementsByClassName('value')[0]
|
||||
let position = { ...movement.position }
|
||||
let pickedObject = this.sdk.viewer.scene.pick(position);
|
||||
if (pickedObject && pickedObject.id && pickedObject.id.type && pickedObject.id.type === "SlopeAspect") {
|
||||
let top = 0
|
||||
let left = 0
|
||||
|
||||
if (this.sdk.viewer && this.sdk.viewer._element) {
|
||||
let element = this.sdk.viewer._element.getElementsByClassName('cesium-widget')[0].getElementsByTagName('canvas')[0]
|
||||
top = element.getBoundingClientRect().top + window.scrollY
|
||||
left = element.getBoundingClientRect().left + window.scrollX
|
||||
}
|
||||
infoBox.style.display = 'block'
|
||||
infoBox.style.left = position.x + 2 + left + 'px'
|
||||
infoBox.style.top = position.y - 20 + top + 'px'
|
||||
vlaElm.innerHTML = '坡度:' + Number(Cesium.Math.toDegrees(pickedObject.id.value || 0).toFixed(2)) + '°'
|
||||
}
|
||||
else {
|
||||
infoBox.style.display = 'none'
|
||||
}
|
||||
}
|
||||
this.event.mouse_move((movement, cartesian) => {
|
||||
let newMovement = {
|
||||
position: { ...movement.endPosition }
|
||||
}
|
||||
mouseEvent(newMovement, cartesian)
|
||||
})
|
||||
this.event.mouse_left(mouseEvent)
|
||||
|
||||
this._camera = {
|
||||
position: this.sdk.viewer.camera.position,
|
||||
heading: this.sdk.viewer.camera.heading,
|
||||
pitch: this.sdk.viewer.camera.pitch,
|
||||
roll: this.sdk.viewer.camera.roll
|
||||
}
|
||||
this.sdk.viewer.scene.preRender.addEventListener(this._watchEvent, this)
|
||||
// this.sdk.viewer.clock.onTick.addEventListener(() => {
|
||||
// console.log(111111)
|
||||
// let infoBox = document.getElementById('SlopeAspect-box')
|
||||
// if(infoBox) {
|
||||
// infoBox.style.display = 'none'
|
||||
// }
|
||||
// })
|
||||
}
|
||||
|
||||
_watchEvent() {
|
||||
if (
|
||||
this._camera.position.x.toFixed(8) !== this.sdk.viewer.camera.position.x.toFixed(8) ||
|
||||
this._camera.position.y.toFixed(8) !== this.sdk.viewer.camera.position.y.toFixed(8) ||
|
||||
this._camera.position.z.toFixed(8) !== this.sdk.viewer.camera.position.z.toFixed(8) ||
|
||||
this._camera.heading.toFixed(8) !== this.sdk.viewer.camera.heading.toFixed(8) ||
|
||||
this._camera.pitch.toFixed(8) !== this.sdk.viewer.camera.pitch.toFixed(8) ||
|
||||
this._camera.roll.toFixed(8) !== this.sdk.viewer.camera.roll.toFixed(8)
|
||||
) {
|
||||
let infoBox = document.getElementById('SlopeAspect-box')
|
||||
if (infoBox) {
|
||||
infoBox.style.display = 'none'
|
||||
}
|
||||
}
|
||||
this._camera = {
|
||||
position: this.sdk.viewer.camera.position,
|
||||
heading: this.sdk.viewer.camera.heading,
|
||||
pitch: this.sdk.viewer.camera.pitch,
|
||||
roll: this.sdk.viewer.camera.roll
|
||||
}
|
||||
}
|
||||
|
||||
//根据坡度值赋值颜色
|
||||
calculateSlopeColor(value, alpha) {
|
||||
// 0°~0.5°为平原0.00872686779075879,rgb(85,182,43)
|
||||
// 0.5°~2°为微斜坡0.03492076949174773,rgb(135,211,43)
|
||||
// 2°~5°为缓斜坡0.08748866352592401,rgb(204,244,44)
|
||||
// 5°~15°为斜坡0.2679491924311227,rgb(245,233,44)
|
||||
// 15°~35°为陡坡0.7002075382097097,rgb(255,138,43)
|
||||
// 35°~55°为峭坡1.4281480067421144,rgb(255,84,43)
|
||||
// 55°~90°为垂直壁,rgb(255,32,43)
|
||||
if (value < 0.00872686779075879) {
|
||||
return "rgba(85,182,43," + alpha + ")";
|
||||
} else if (value < 0.03492076949174773) {
|
||||
return "rgba(135,211,43," + alpha + ")";
|
||||
} else if (value < 0.08748866352592401) {
|
||||
return "rgba(204,244,44," + alpha + ")";
|
||||
} else if (value < 0.2679491924311227) {
|
||||
return "rgba(245,233,44," + alpha + ")";
|
||||
} else if (value < 0.7002075382097097) {
|
||||
return "rgba(255,138,43," + alpha + ")";
|
||||
} else if (value < 1.4281480067421144) {
|
||||
return "rgba(255,84,43," + alpha + ")";
|
||||
} else {
|
||||
return "rgba(255,32,43," + alpha + ")";
|
||||
}
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.result && this.result.forEach((element) => {
|
||||
this.viewer.scene.primitives.remove(element);
|
||||
});
|
||||
this.result = [];
|
||||
this.sdk.viewer.scene.preRender.removeEventListener(this._watchEvent, this)
|
||||
}
|
||||
}
|
||||
export default SlopeAspect;
|
||||
92
src/Obj/Analysis/Submerge/_element.js
Normal file
92
src/Obj/Analysis/Submerge/_element.js
Normal file
@ -0,0 +1,92 @@
|
||||
function html() {
|
||||
return `
|
||||
<span class="custom-divider"></span>
|
||||
<div class="div-item">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<span class="label">水量</span>
|
||||
<div class="input-number input-number-unit-3">
|
||||
<input class="input" type="number" title="" name="waterVolume">
|
||||
<span class="unit">m³</span>
|
||||
<span class="arrow"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<span class="label">最小水位</span>
|
||||
<div class="input-number input-number-unit-3">
|
||||
<input class="input" type="number" title="" name="minWaterLevel">
|
||||
<span class="unit">m</span>
|
||||
<span class="arrow"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<span class="label">水面面积</span>
|
||||
<div class="input-number input-number-unit-3">
|
||||
<input class="input area" type="number" readonly="readonly" type="text">
|
||||
<span class="unit">㎡</span>
|
||||
<span class="arrow"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<span class="label">最大水位</span>
|
||||
<div class="input-number input-number-unit-3">
|
||||
<input class="input" type="number" title="" name="maxWaterLevel">
|
||||
<span class="unit">m</span>
|
||||
<span class="arrow"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="custom-divider"></span>
|
||||
<div class="div-item">
|
||||
<div class="row subtitle-box">
|
||||
<span class="subtitle">上升速度</span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<input type="range" max="50" min="0" step="0.01" name="risingSpeed">
|
||||
<div class="input-number input-number-unit-3" style="flex: 0 0 110px;margin-left: 10px;">
|
||||
<input class="input" type="number" title="" name="risingSpeed">
|
||||
<span class="unit">m/s</span>
|
||||
<span class="arrow"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="custom-divider"></span>
|
||||
<div class="div-item">
|
||||
<div class="row">
|
||||
<div class="col operate-btn-box">
|
||||
<button class="draw"><svg class="icon-draw"><use xlink:href="#yj-icon-draw"></use></svg>绘制范围</button>
|
||||
<button class="flyto"><svg class="icon-positions"><use xlink:href="#yj-icon-positions"></use></svg>定位</button>
|
||||
<button class="reset"><svg class="icon-reset"><use xlink:href="#yj-icon-reset"></use></svg>重置</button>
|
||||
<button class="analog"><svg class="icon-play"><use xlink:href="#yj-icon-play"></use></svg>开始模拟</button>
|
||||
<button class="pause" style="margin-right: 0px;"><svg class="icon-pause"><use xlink:href="#yj-icon-pause"></use></svg>暂停</button>
|
||||
<button class="start" style="display: none;margin-right: 0px;"><svg class="icon-play"><use xlink:href="#yj-icon-play"></use></svg>播放</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="table">
|
||||
<div class="table-head">
|
||||
<div class="tr">
|
||||
<div class="th">序号</div>
|
||||
<div class="th">经度</div>
|
||||
<div class="th">纬度</div>
|
||||
<div class="th">高程</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-body">
|
||||
</div>
|
||||
<div class="table-empty">
|
||||
<div class="empty-img"></div>
|
||||
<p>暂无数据</p>
|
||||
</div>
|
||||
</div>
|
||||
<span class="custom-divider" style="margin-top: 20px;"></span>
|
||||
`
|
||||
}
|
||||
|
||||
export { html }
|
||||
484
src/Obj/Analysis/Submerge/index.js
Normal file
484
src/Obj/Analysis/Submerge/index.js
Normal file
@ -0,0 +1,484 @@
|
||||
import Dialog from '../../../BaseDialog';
|
||||
import { html } from "./_element";
|
||||
import DrawPolygon from "../../../Draw/drawPolygon"
|
||||
import Tools from "../../../Tools";
|
||||
import { closeRotateAround, closeViewFollow} from '../../../Global/global'
|
||||
class Submerge extends Tools {
|
||||
/**
|
||||
* @constructor
|
||||
* @param sdk
|
||||
* @description 淹没效果
|
||||
* */
|
||||
constructor(sdk, options = {}, _Dialog = {}) {
|
||||
super(sdk, options);
|
||||
this.sdk = sdk
|
||||
this.options = {}
|
||||
this.options.name = options.name
|
||||
this.options.risingSpeed = 1
|
||||
this.options.minWaterLevel = 0
|
||||
this.options.maxWaterLevel = 0
|
||||
this.options.waterVolume = 0
|
||||
this.currentWaterLaver
|
||||
this.color = '#00d9ff66'
|
||||
this.Dialog = _Dialog
|
||||
this.Draw = new DrawPolygon(this.sdk)
|
||||
this.positions
|
||||
this.status = true
|
||||
this.area = 0
|
||||
this._elms = {};
|
||||
YJ.Analysis.Analyses.push(this)
|
||||
Submerge.EditBox(this)
|
||||
// Submerge.create(this)
|
||||
}
|
||||
|
||||
static create(that) {
|
||||
that.Draw.start((a, positions) => {
|
||||
if (!positions || positions.length < 3) {
|
||||
let _error = '至少需要三个坐标!'
|
||||
console.warn(_error)
|
||||
window.ELEMENT &&
|
||||
window.ELEMENT.Message({
|
||||
message: _error,
|
||||
type: 'warning',
|
||||
duration: 1500
|
||||
})
|
||||
return
|
||||
}
|
||||
that.destroy()
|
||||
if (!positions || positions.length == 0) {
|
||||
that.positions = []
|
||||
that._positions = []
|
||||
that.options.minWaterLevel = 0
|
||||
that.options.maxWaterLevel = 0
|
||||
that.options.waterVolume = 0
|
||||
that.area = 0
|
||||
return
|
||||
}
|
||||
let fromDegreesArray = []
|
||||
that.positions = positions
|
||||
that._positions = positions
|
||||
that.options.minWaterLevel = positions[0].alt
|
||||
for (let i = 0; i < positions.length; i++) {
|
||||
if (that.options.minWaterLevel > positions[i].alt) {
|
||||
that.options.minWaterLevel = positions[i].alt
|
||||
}
|
||||
fromDegreesArray.push(positions[i].lng, positions[i].lat)
|
||||
}
|
||||
// for (let i = 0; i < positions.length; i++) {
|
||||
// fromDegreesArray.push(positions[i].lng, positions[i].lat, that.options.minWaterLevel)
|
||||
// }
|
||||
let pos = Cesium.Cartesian3.fromDegreesArray(fromDegreesArray)
|
||||
that.currentWaterLaver = that.options.minWaterLevel
|
||||
that.entity = that.sdk.viewer.entities.add({
|
||||
polygon: {
|
||||
hierarchy: new Cesium.PolygonHierarchy(pos),
|
||||
height: new Cesium.CallbackProperty(function () {
|
||||
return that.options.minWaterLevel
|
||||
}, false),
|
||||
extrudedHeight: new Cesium.CallbackProperty(function () {
|
||||
return that.currentWaterLaver
|
||||
}, false),
|
||||
material: Cesium.Color.fromCssColorString(that.color),
|
||||
},
|
||||
})
|
||||
that.area = that.computeArea(positions)
|
||||
if (that.TweenAnimate) {
|
||||
TWEEN.remove(that.TweenAnimate)
|
||||
that.TweenAnimate = null
|
||||
}
|
||||
let contentElm = that._DialogObject._element.body
|
||||
let pauseBtn = contentElm.getElementsByClassName('pause')[0];
|
||||
let startBtn = contentElm.getElementsByClassName('start')[0];
|
||||
startBtn.style.display = 'flex'
|
||||
pauseBtn.style.display = 'none'
|
||||
// that.move()
|
||||
// Submerge.EditBox(that)
|
||||
})
|
||||
}
|
||||
|
||||
static async EditBox(that) {
|
||||
if (that._DialogObject && that._DialogObject.close) {
|
||||
that._DialogObject.close()
|
||||
that._DialogObject = null
|
||||
}
|
||||
that._DialogObject = await new Dialog(that.sdk.viewer._container, {
|
||||
title: '淹没分析', left: '180px', top: '100px',
|
||||
closeCallBack: () => {
|
||||
that.destroy()
|
||||
that.Dialog.closeCallBack && that.Dialog.closeCallBack()
|
||||
},
|
||||
})
|
||||
await that._DialogObject.init()
|
||||
that._DialogObject._element.body.className = that._DialogObject._element.body.className + ' submerge'
|
||||
let contentElm = document.createElement('div');
|
||||
contentElm.innerHTML = html()
|
||||
that._DialogObject.contentAppChild(contentElm)
|
||||
let stopBtn = document.createElement('button');
|
||||
stopBtn.className = 'el-button'
|
||||
stopBtn.innerHTML = '暂停'
|
||||
stopBtn.style.width = '80px'
|
||||
|
||||
let drawBtn = contentElm.getElementsByClassName('draw')[0]
|
||||
drawBtn.addEventListener('click', () => {
|
||||
Submerge.create(that)
|
||||
})
|
||||
let analogBtn = contentElm.getElementsByClassName('analog')[0];
|
||||
analogBtn.addEventListener('click', () => {
|
||||
that.move()
|
||||
})
|
||||
let flytoBtn = contentElm.getElementsByClassName('flyto')[0];
|
||||
flytoBtn.addEventListener('click', () => {
|
||||
that.flyTo()
|
||||
})
|
||||
let resetBtn = contentElm.getElementsByClassName('reset')[0];
|
||||
resetBtn.addEventListener('click', () => {
|
||||
that.restart()
|
||||
})
|
||||
let pauseBtn = contentElm.getElementsByClassName('pause')[0];
|
||||
let startBtn = contentElm.getElementsByClassName('start')[0];
|
||||
pauseBtn.addEventListener('click', () => {
|
||||
that.pause()
|
||||
pauseBtn.style.display = 'none'
|
||||
startBtn.style.display = 'flex'
|
||||
})
|
||||
startBtn.addEventListener('click', () => {
|
||||
that.start()
|
||||
startBtn.style.display = 'none'
|
||||
pauseBtn.style.display = 'flex'
|
||||
})
|
||||
|
||||
// that._DialogObject.footAppChild(stopBtn)
|
||||
// that._DialogObject.footAppChild(resetBtn)
|
||||
// that._DialogObject.footAppChild(flytoBtn)
|
||||
// that._DialogObject.footAppChild(analogBtn)
|
||||
// that._DialogObject.footAppChild(drawBtn)
|
||||
|
||||
// 速度
|
||||
let e_risingSpeed = contentElm.querySelectorAll("input[name='risingSpeed']")
|
||||
e_risingSpeed[0].value = that.options.risingSpeed
|
||||
e_risingSpeed[1].value = that.options.risingSpeed
|
||||
e_risingSpeed[0].addEventListener('input', e => {
|
||||
that.options.risingSpeed = Number(e.target.value);
|
||||
});
|
||||
e_risingSpeed[1].addEventListener('input', e => {
|
||||
if (e.data != '.') {
|
||||
let value = Number(e.target.value)
|
||||
let max = Number(e_risingSpeed[0].max)
|
||||
let min = Number(e_risingSpeed[0].min)
|
||||
if (value > max) {
|
||||
that.options.risingSpeed = max;
|
||||
}
|
||||
else if (value < min) {
|
||||
that.options.risingSpeed = min;
|
||||
}
|
||||
else {
|
||||
that.options.risingSpeed = Math.floor(value * 100) / 100;
|
||||
}
|
||||
}
|
||||
});
|
||||
Object.defineProperty(that.options, 'risingSpeed', {
|
||||
get() {
|
||||
return e_risingSpeed[0].value
|
||||
},
|
||||
set(value) {
|
||||
e_risingSpeed[0].value = value
|
||||
e_risingSpeed[1].value = value
|
||||
}
|
||||
})
|
||||
that.waterLevel = that.options.maxWaterLevel - that.options.minWaterLevel
|
||||
// 最低水位
|
||||
let e_minWaterLevel = contentElm.querySelector("input[name='minWaterLevel']")
|
||||
e_minWaterLevel.value = that.options.minWaterLevel
|
||||
e_minWaterLevel.addEventListener('input', e => {
|
||||
if (e.data != '.') {
|
||||
let value = Number(e.target.value)
|
||||
if (value > 999999999) {
|
||||
value = 999999999
|
||||
}
|
||||
if (value < 0) {
|
||||
value = 0
|
||||
}
|
||||
that.options.minWaterLevel = Math.floor(value * 10000) / 10000;
|
||||
that.options.maxWaterLevel = that.options.minWaterLevel + that.waterLevel;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(that.options, 'minWaterLevel', {
|
||||
get() {
|
||||
return Number(e_minWaterLevel.value)
|
||||
},
|
||||
set(value) {
|
||||
e_minWaterLevel.value = Math.floor(Number(value) * 10000) / 10000;
|
||||
}
|
||||
})
|
||||
|
||||
// 最高水位
|
||||
let e_maxWaterLevel = contentElm.querySelector("input[name='maxWaterLevel']")
|
||||
e_maxWaterLevel.value = that.options.maxWaterLevel
|
||||
e_maxWaterLevel.addEventListener('input', e => {
|
||||
if (e.data != '.') {
|
||||
let value = Number(e.target.value)
|
||||
if (value > 999999999) {
|
||||
value = 999999999
|
||||
}
|
||||
if (value < 0) {
|
||||
value = 0
|
||||
}
|
||||
if (value < that.options.minWaterLevel) {
|
||||
that.options.maxWaterLevel = that.options.minWaterLevel;
|
||||
}
|
||||
else {
|
||||
that.options.maxWaterLevel = Math.floor(value * 10000) / 10000;
|
||||
}
|
||||
that.waterLevel = that.options.maxWaterLevel - that.options.minWaterLevel
|
||||
that.options.waterVolume = Number((that.waterLevel * that.area).toFixed(4))
|
||||
}
|
||||
});
|
||||
Object.defineProperty(that.options, 'maxWaterLevel', {
|
||||
get() {
|
||||
return Number(e_maxWaterLevel.value)
|
||||
},
|
||||
set(value) {
|
||||
if (isNaN(value)) {
|
||||
value = 0
|
||||
}
|
||||
e_maxWaterLevel.value = Math.floor(Number(value) * 10000) / 10000;
|
||||
}
|
||||
})
|
||||
|
||||
// 水量
|
||||
let e_waterVolume = contentElm.querySelector("input[name='waterVolume']")
|
||||
e_waterVolume.value = that.options.waterVolume
|
||||
e_waterVolume.addEventListener('input', e => {
|
||||
if (e.data != '.') {
|
||||
let value = Number(e.target.value)
|
||||
if (value > 99999999999999) {
|
||||
value = 99999999999999
|
||||
}
|
||||
if (value < 0) {
|
||||
value = 0
|
||||
}
|
||||
that.options.waterVolume = Math.floor(value * 10000) / 10000;
|
||||
if (that.area) {
|
||||
that.waterLevel = Number((that.options.waterVolume / that.area).toFixed(4))
|
||||
that.options.maxWaterLevel = that.options.minWaterLevel + that.waterLevel
|
||||
}
|
||||
}
|
||||
});
|
||||
Object.defineProperty(that.options, 'waterVolume', {
|
||||
get() {
|
||||
return Number(e_waterVolume.value)
|
||||
},
|
||||
set(value) {
|
||||
e_waterVolume.value = value
|
||||
}
|
||||
})
|
||||
|
||||
// 面积
|
||||
let e_area = contentElm.getElementsByClassName('area')[0]
|
||||
e_area.value = that.area
|
||||
Object.defineProperty(that, 'area', {
|
||||
get() {
|
||||
return Number(e_area.value)
|
||||
},
|
||||
set(value) {
|
||||
e_area.value = value
|
||||
that.waterLevel = Number((that.options.waterVolume / that.area).toFixed(4))
|
||||
that.options.maxWaterLevel = that.options.minWaterLevel + that.waterLevel
|
||||
}
|
||||
})
|
||||
// 表格
|
||||
let e_tableBody = contentElm.getElementsByClassName('table-body')[0]
|
||||
let e_tableEmpty = contentElm.getElementsByClassName('table-empty')[0]
|
||||
Object.defineProperty(that, 'positions', {
|
||||
get() {
|
||||
return that._positions
|
||||
},
|
||||
set(value) {
|
||||
if (value && value.length > 0) {
|
||||
e_tableEmpty.style.display = 'none'
|
||||
let tr = ''
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
tr = tr + `<div class="tr">
|
||||
<div class="td">${i + 1}</div>
|
||||
<div class="td">${Number(value[i].lng.toFixed(10))}</div>
|
||||
<div class="td">${Number(value[i].lat.toFixed(10))}</div>
|
||||
<div class="td">${Number(value[i].alt.toFixed(4))}</div>
|
||||
</div>`
|
||||
}
|
||||
e_tableBody.innerHTML = tr
|
||||
}
|
||||
else {
|
||||
e_tableBody.innerHTML = ''
|
||||
e_tableEmpty.style.display = 'flex'
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
move() {
|
||||
if (this.TweenAnimate) {
|
||||
TWEEN.remove(this.TweenAnimate)
|
||||
}
|
||||
let totalTime = ((this.options.maxWaterLevel - this.options.minWaterLevel) / this.options.risingSpeed) * 1000
|
||||
this.TweenAnimate = new TWEEN.Tween({ waterLevel: this.options.minWaterLevel }).to({ waterLevel: this.options.maxWaterLevel }, totalTime).delay(this.delay).easing(TWEEN.Easing.Linear.None).onUpdate(async (r, a) => {
|
||||
this.currentWaterLaver = r.waterLevel
|
||||
}).start()
|
||||
let contentElm = this._DialogObject._element.body
|
||||
let pauseBtn = contentElm.getElementsByClassName('pause')[0];
|
||||
let startBtn = contentElm.getElementsByClassName('start')[0];
|
||||
startBtn.style.display = 'none'
|
||||
pauseBtn.style.display = 'flex'
|
||||
}
|
||||
|
||||
restart() {
|
||||
this.currentWaterLaver = this.options.minWaterLevel
|
||||
let isPaused = false
|
||||
if (this.TweenAnimate) {
|
||||
isPaused = this.TweenAnimate._isPaused
|
||||
TWEEN.remove(this.TweenAnimate)
|
||||
}
|
||||
let totalTime = ((this.options.maxWaterLevel - this.options.minWaterLevel) / this.options.risingSpeed) * 1000
|
||||
this.TweenAnimate = new TWEEN.Tween({ waterLevel: this.options.minWaterLevel }).to({ waterLevel: this.options.maxWaterLevel }, totalTime).delay(this.delay).easing(TWEEN.Easing.Linear.None).onUpdate(async (r, a) => {
|
||||
this.currentWaterLaver = r.waterLevel
|
||||
}).start()
|
||||
if (isPaused) {
|
||||
this.pause()
|
||||
}
|
||||
}
|
||||
|
||||
start() {
|
||||
if (this.TweenAnimate) {
|
||||
this.TweenAnimate.resume()
|
||||
}
|
||||
}
|
||||
pause() {
|
||||
if (this.TweenAnimate) {
|
||||
this.TweenAnimate.pause()
|
||||
}
|
||||
}
|
||||
|
||||
calculateVolumeHeight() {
|
||||
that.options.maxWaterLevel
|
||||
}
|
||||
|
||||
/**
|
||||
* 飞到
|
||||
*/
|
||||
flyTo() {
|
||||
if (!this.positions || this.positions.length === 0) {
|
||||
return
|
||||
}
|
||||
closeRotateAround(this.sdk)
|
||||
closeViewFollow(this.sdk)
|
||||
|
||||
let positionArray = []
|
||||
for (let i = 0; i < this.positions.length; i++) {
|
||||
let fromDegrees = Cesium.Cartesian3.fromDegrees(this.positions[i].lng, this.positions[i].lat, this.options.maxWaterLevel)
|
||||
positionArray.push(fromDegrees.x, fromDegrees.y, fromDegrees.z)
|
||||
}
|
||||
let BoundingSphere = Cesium.BoundingSphere.fromVertices(positionArray)
|
||||
this.sdk.viewer.camera.flyToBoundingSphere(BoundingSphere, {
|
||||
offset: {
|
||||
heading: Cesium.Math.toRadians(0.0),
|
||||
pitch: Cesium.Math.toRadians(-90.0),
|
||||
roll: Cesium.Math.toRadians(0.0)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
destroy() {
|
||||
if (this.TweenAnimate) {
|
||||
TWEEN.remove(this.TweenAnimate)
|
||||
}
|
||||
this.Draw.end()
|
||||
this.sdk.viewer.entities.remove(this.entity)
|
||||
this.entity = null
|
||||
}
|
||||
|
||||
static EventBinding(that, elements) {
|
||||
for (let i = 0; i < elements.length; i++) {
|
||||
let Event = []
|
||||
let isEvent = false
|
||||
let removeName = []
|
||||
if (!elements[i] || !elements[i].attributes) {
|
||||
continue;
|
||||
}
|
||||
for (let m of elements[i].attributes) {
|
||||
switch (m.name) {
|
||||
case '@model': {
|
||||
isEvent = true
|
||||
if (elements[i].type == 'checkbox') {
|
||||
Event.push((e) => { that[m.value] = e.target.checked })
|
||||
elements[i].checked = that[m.value]
|
||||
}
|
||||
else {
|
||||
Event.push((e) => {
|
||||
let value = e.target.value
|
||||
if (e.target.type == 'number') {
|
||||
value = Number(value)
|
||||
}
|
||||
that[m.value] = value
|
||||
})
|
||||
if (elements[i].nodeName == 'IMG') {
|
||||
elements[i].src = that[m.value]
|
||||
}
|
||||
else {
|
||||
elements[i].value = that[m.value]
|
||||
}
|
||||
}
|
||||
if (that._elms[m.value]) {
|
||||
that._elms[m.value].push(elements[i])
|
||||
}
|
||||
else {
|
||||
that._elms[m.value] = [elements[i]]
|
||||
}
|
||||
removeName.push(m.name)
|
||||
break;
|
||||
}
|
||||
case '@click': {
|
||||
elements[i].addEventListener('click', (e) => {
|
||||
if (typeof (that[m.value]) === 'function') {
|
||||
that[m.value](e)
|
||||
}
|
||||
});
|
||||
removeName.push(m.name)
|
||||
// elements[i].attributes.removeNamedItem(m.name)
|
||||
break;
|
||||
}
|
||||
case '@change': {
|
||||
isEvent = true
|
||||
Event.push((e) => {
|
||||
let value = e.target.value
|
||||
if (e.target.type == 'number' && value != '') {
|
||||
value = Number(value)
|
||||
e.target.value = value
|
||||
}
|
||||
if (typeof (that[m.value]) === 'function') {
|
||||
that[m.value](e, value)
|
||||
}
|
||||
})
|
||||
break;
|
||||
}
|
||||
}
|
||||
// elements[i].attributes[m] = undefined
|
||||
}
|
||||
for (let n = 0; n < removeName.length; n++) {
|
||||
elements[i].attributes.removeNamedItem(removeName[n])
|
||||
}
|
||||
|
||||
if (isEvent) {
|
||||
let ventType = 'input'
|
||||
if (elements[i].tagName != 'INPUT' || elements[i].type == 'checkbox') {
|
||||
ventType = 'change'
|
||||
}
|
||||
elements[i].addEventListener(ventType, (e) => {
|
||||
for (let t = 0; t < Event.length; t++) {
|
||||
Event[t](e)
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Submerge
|
||||
32
src/Obj/Analysis/TerrainExcavation/_element.js
Normal file
32
src/Obj/Analysis/TerrainExcavation/_element.js
Normal file
@ -0,0 +1,32 @@
|
||||
function html() {
|
||||
return `
|
||||
<span class="custom-divider"></span>
|
||||
<div class="div-item">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<span class="label" style="flex: 0 0 70px;">挖掘高度</span>
|
||||
<div class="input-number input-number-unit-1">
|
||||
<input class="input" type="number" title="" min="0" max="5000000" name="height">
|
||||
<span class="unit">m</span>
|
||||
<span class="arrow"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="custom-divider"></span>
|
||||
<div class="div-item">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<span class="label">绘制开挖区域</span>
|
||||
<button class="start-excavation"><svg class="icon-edit"><use xlink:href="#yj-icon-edit"></use></svg>绘制</button>
|
||||
</div>
|
||||
<div class="col">
|
||||
<span class="label">清除开挖区域</span>
|
||||
<button class="clean-excavation"><svg class="icon-close"><use xlink:href="#yj-icon-close"></use></svg>清除</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
||||
export { html }
|
||||
459
src/Obj/Analysis/TerrainExcavation/index.js
Normal file
459
src/Obj/Analysis/TerrainExcavation/index.js
Normal file
@ -0,0 +1,459 @@
|
||||
import Tools from "../../../Tools";
|
||||
import DrawPolygon from "../../../Draw/drawPolygon"
|
||||
import Dialog from '../../../BaseDialog';
|
||||
import { html } from "./_element";
|
||||
|
||||
let ExcavationFaces = []
|
||||
class TerrainExcavation extends Tools {
|
||||
/**
|
||||
* @constructor
|
||||
* @description 地形开挖
|
||||
* @param sdk
|
||||
* */
|
||||
constructor(sdk, options = {}) {
|
||||
super(sdk)
|
||||
this.viewer = sdk.viewer
|
||||
this.options = options || {};
|
||||
this.options.height = (this.options.height || this.options.height === 0) ? this.options.height : 10;
|
||||
this.options.show = (this.options.show || this.options.show === false) ? this.options.show : true;
|
||||
this.bottomImg = this.getSourceRootPath() + '/img/excavationregion_top.jpg';
|
||||
this.wallImg = this.getSourceRootPath() + '/img/excavationregion_side.jpg';
|
||||
this.splitNum = Cesium.defaultValue(options.splitNum, 50);
|
||||
this.Draw = new DrawPolygon(this.sdk)
|
||||
this.bottomMaterial = Cesium.Material.fromType('Color', {
|
||||
color: Cesium.Color.fromAlpha(Cesium.Color.fromCssColorString('#735d4f'))
|
||||
})
|
||||
this.wallMaterial = Cesium.Material.fromType('Color', {
|
||||
color: Cesium.Color.fromAlpha(Cesium.Color.fromCssColorString('#976b4e'))
|
||||
})
|
||||
let imageBottom = new Image();
|
||||
let wallBottom = new Image();
|
||||
imageBottom.src = this.bottomImg;
|
||||
wallBottom.src = this.wallImg;
|
||||
imageBottom.crossOrigin = "Anonymous";
|
||||
wallBottom.crossOrigin = "Anonymous";
|
||||
imageBottom.onload = () => {
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = imageBottom.width;
|
||||
canvas.height = imageBottom.height;
|
||||
const context = canvas.getContext('2d');
|
||||
context.drawImage(imageBottom, 0, 0, imageBottom.width, imageBottom.height);
|
||||
const base64 = canvas.toDataURL('image/jpg');
|
||||
this.bottomMaterial = new Cesium.Material({
|
||||
fabric: {
|
||||
type: "Image",
|
||||
uniforms: {
|
||||
image: base64,
|
||||
},
|
||||
},
|
||||
});
|
||||
if (this.bottomSurface) {
|
||||
this.bottomSurface.appearance.material = this.bottomMaterial;
|
||||
}
|
||||
}
|
||||
wallBottom.onload = () => {
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = wallBottom.width;
|
||||
canvas.height = wallBottom.height;
|
||||
const context = canvas.getContext('2d');
|
||||
context.drawImage(wallBottom, 0, 0, wallBottom.width, wallBottom.height);
|
||||
const base64 = canvas.toDataURL('image/jpg');
|
||||
this.wallMaterial = new Cesium.Material({
|
||||
fabric: {
|
||||
type: "Image",
|
||||
uniforms: {
|
||||
image: base64,
|
||||
},
|
||||
},
|
||||
});
|
||||
if (this.wellWall) {
|
||||
this.wellWall.appearance.material = this.wallMaterial;
|
||||
}
|
||||
}
|
||||
|
||||
this.init();
|
||||
}
|
||||
get show() {
|
||||
return this.options.show
|
||||
}
|
||||
set show(v) {
|
||||
this.options.show = v;
|
||||
this.switchExcavate(v);
|
||||
}
|
||||
get height() {
|
||||
return this.options.height
|
||||
}
|
||||
set height(v) {
|
||||
this.options.height = v;
|
||||
// this.updateExcavateDepth(v);
|
||||
}
|
||||
init() {
|
||||
TerrainExcavation.edit(this, true)
|
||||
}
|
||||
static async edit(that, state) {
|
||||
if (that._DialogObject && that._DialogObject.close) {
|
||||
that._DialogObject.close()
|
||||
that._DialogObject = null
|
||||
}
|
||||
if (state) {
|
||||
that._DialogObject = await new Dialog(that.sdk.viewer._container, {
|
||||
title: '地形开挖',
|
||||
closeCallBack: () => {
|
||||
},
|
||||
})
|
||||
await that._DialogObject.init()
|
||||
that._DialogObject._element.body.className = that._DialogObject._element.body.className + ' terrain-excavation'
|
||||
let contentElm = document.createElement('div');
|
||||
contentElm.innerHTML = html()
|
||||
that._DialogObject.contentAppChild(contentElm)
|
||||
|
||||
// 开始
|
||||
let e_start = contentElm.getElementsByClassName('start-excavation')[0]
|
||||
e_start.addEventListener('click', () => {
|
||||
that.startCreate()
|
||||
});
|
||||
// 清除
|
||||
let e_clean = contentElm.getElementsByClassName('clean-excavation')[0]
|
||||
e_clean.addEventListener('click', () => {
|
||||
that.clear()
|
||||
});
|
||||
|
||||
// 高度值
|
||||
let e_height = contentElm.querySelector("input[name='height']")
|
||||
e_height.value = that.height
|
||||
e_height.addEventListener('change', (e) => {
|
||||
let value = e.target.value
|
||||
value = Number(value)
|
||||
if (value < 0.01) {
|
||||
value = 0.01
|
||||
e.target.value = value
|
||||
that.height = value;
|
||||
}
|
||||
})
|
||||
e_height.addEventListener('blur', (e) => {
|
||||
let value = e.target.value
|
||||
value = Number(value)
|
||||
if ((e.target.max) && value > Number(e.target.max)) {
|
||||
value = Number(e.target.max)
|
||||
}
|
||||
if (value < 0.01) {
|
||||
value = 0.01
|
||||
}
|
||||
e.target.value = value
|
||||
that.height = value;
|
||||
});
|
||||
|
||||
} else {
|
||||
if (that._DialogObject && that._DialogObject.close) {
|
||||
that._DialogObject.close()
|
||||
that._DialogObject = null
|
||||
}
|
||||
}
|
||||
}
|
||||
startCreate() {
|
||||
this.Draw.start((e, positions) => {
|
||||
if (!positions || positions.length <= 2) {
|
||||
window.ELEMENT && window.ELEMENT.Message({
|
||||
message: '至少拥有三个坐标位置!',
|
||||
type: 'warning',
|
||||
duration: 1500
|
||||
});
|
||||
return
|
||||
}
|
||||
if(!this.isConvex(positions)) {
|
||||
window.ELEMENT && window.ELEMENT.Message({
|
||||
message: '不支持凹多边形',
|
||||
type: 'warning',
|
||||
duration: 1500
|
||||
});
|
||||
console.log('不支持凹多边形')
|
||||
return
|
||||
}
|
||||
this.updateData(positions)
|
||||
})
|
||||
}
|
||||
updateData(activePoints) {
|
||||
let viewer = this.viewer;
|
||||
this.clear();
|
||||
let clippingPlanesList = [];
|
||||
let array = []
|
||||
for (let i = 0; i < activePoints.length; i++) {
|
||||
array.push([activePoints[i].lng, activePoints[i].lat])
|
||||
}
|
||||
array.push([activePoints[0].lng, activePoints[0].lat])
|
||||
let clockwiseRing = turf.lineString(array);
|
||||
// 是否顺时针
|
||||
let boolDiff = turf.booleanClockwise(clockwiseRing);
|
||||
this.excavateMinHeight = 9999;
|
||||
for (let index = 0; index < activePoints.length; ++index) {
|
||||
let s = (index + 1) % activePoints.length;
|
||||
let position1 = Cesium.Cartesian3.fromDegrees(activePoints[index].lng, activePoints[index].lat, activePoints[index].alt)
|
||||
let position2 = Cesium.Cartesian3.fromDegrees(activePoints[s].lng, activePoints[s].lat, activePoints[s].alt)
|
||||
let curMidPoint = Cesium.Cartesian3.midpoint(
|
||||
position1,
|
||||
position2,
|
||||
new Cesium.Cartesian3()
|
||||
);
|
||||
let cartographic = Cesium.Cartographic.fromCartesian(position1);
|
||||
let curHeight =
|
||||
viewer.scene.globe.getHeight(cartographic) || cartographic.height;
|
||||
if (curHeight < this.excavateMinHeight) {
|
||||
this.excavateMinHeight = curHeight;
|
||||
}
|
||||
let curMidPointNormal = Cesium.Cartesian3.normalize(
|
||||
curMidPoint,
|
||||
new Cesium.Cartesian3()
|
||||
);
|
||||
let curMidPointDifference = boolDiff
|
||||
? Cesium.Cartesian3.subtract(
|
||||
position1,
|
||||
curMidPoint,
|
||||
new Cesium.Cartesian3()
|
||||
)
|
||||
: Cesium.Cartesian3.subtract(
|
||||
position2,
|
||||
curMidPoint,
|
||||
new Cesium.Cartesian3()
|
||||
);
|
||||
curMidPointDifference = Cesium.Cartesian3.normalize(
|
||||
curMidPointDifference,
|
||||
curMidPointDifference
|
||||
);
|
||||
let curMidPointCross = Cesium.Cartesian3.cross(
|
||||
curMidPointDifference,
|
||||
curMidPointNormal,
|
||||
new Cesium.Cartesian3()
|
||||
);
|
||||
curMidPointCross = Cesium.Cartesian3.normalize(
|
||||
curMidPointCross,
|
||||
curMidPointCross
|
||||
);
|
||||
let plane = new Cesium.Plane(curMidPointCross, 0);
|
||||
let distance = Cesium.Plane.getPointDistance(plane, curMidPoint);
|
||||
clippingPlanesList.push(
|
||||
new Cesium.ClippingPlane(curMidPointCross, distance)
|
||||
);
|
||||
}
|
||||
this.viewer.scene.globe.clippingPlanes = new Cesium.ClippingPlaneCollection(
|
||||
{
|
||||
planes: clippingPlanesList,
|
||||
edgeWidth: 1,
|
||||
edgeColor: Cesium.Color.WHITE,
|
||||
enabled: true,
|
||||
}
|
||||
);
|
||||
this.prepareWell(activePoints);
|
||||
this.createWell(this.wellData);
|
||||
// this.viewer.entities.remove(this.drawGeomtry);
|
||||
}
|
||||
|
||||
clear() {
|
||||
if (this.viewer.scene.globe.clippingPlanes) {
|
||||
this.viewer.scene.globe.clippingPlanes.removeAll();
|
||||
this.viewer.scene.primitives.remove(this.bottomSurface);
|
||||
this.viewer.scene.primitives.remove(this.wellWall);
|
||||
this.viewer.scene.render();
|
||||
}
|
||||
for (let i = ExcavationFaces.length - 1; i >= 0; i--) {
|
||||
this.viewer.scene.primitives.remove(ExcavationFaces[i]);
|
||||
}
|
||||
ExcavationFaces = []
|
||||
this.Draw && this.Draw.end()
|
||||
}
|
||||
destroy() {
|
||||
this.clear()
|
||||
}
|
||||
//计算并更新wellData
|
||||
prepareWell(activePoints) {
|
||||
let pointLength = activePoints.length;
|
||||
let heightDiff = this.excavateMinHeight - this.height;
|
||||
let no_height_top = [],
|
||||
bottom_pos = [],
|
||||
lerp_pos = [];
|
||||
for (let l = 0; l < pointLength; l++) {
|
||||
let u = l == pointLength - 1 ? 0 : l + 1;
|
||||
let point0 = [
|
||||
Cesium.Cartographic.fromDegrees(activePoints[l].lng, activePoints[l].lat, activePoints[l].alt).longitude,
|
||||
Cesium.Cartographic.fromDegrees(activePoints[l].lng, activePoints[l].lat, activePoints[l].alt).latitude,
|
||||
];
|
||||
let point1 = [
|
||||
Cesium.Cartographic.fromDegrees(activePoints[u].lng, activePoints[u].lat, activePoints[u].alt).longitude,
|
||||
Cesium.Cartographic.fromDegrees(activePoints[u].lng, activePoints[u].lat, activePoints[u].alt).latitude,
|
||||
];
|
||||
if (0 == l) {
|
||||
lerp_pos.push(new Cesium.Cartographic(point0[0], point0[1]));
|
||||
bottom_pos.push(
|
||||
Cesium.Cartesian3.fromRadians(point0[0], point0[1], heightDiff)
|
||||
);
|
||||
no_height_top.push(
|
||||
Cesium.Cartesian3.fromRadians(point0[0], point0[1], 0)
|
||||
);
|
||||
}
|
||||
for (let p = 1; p <= this.splitNum; p++) {
|
||||
let m = Cesium.Math.lerp(point0[0], point1[0], p / this.splitNum);
|
||||
let g = Cesium.Math.lerp(point0[1], point1[1], p / this.splitNum);
|
||||
(l == pointLength - 1 && p == this.splitNum) ||
|
||||
(lerp_pos.push(new Cesium.Cartographic(m, g)),
|
||||
bottom_pos.push(Cesium.Cartesian3.fromRadians(m, g, heightDiff)),
|
||||
no_height_top.push(Cesium.Cartesian3.fromRadians(m, g, 0)));
|
||||
}
|
||||
}
|
||||
this.wellData = {
|
||||
lerp_pos: lerp_pos,
|
||||
bottom_pos: bottom_pos,
|
||||
no_height_top: no_height_top,
|
||||
};
|
||||
}
|
||||
//开始创建底面和侧面
|
||||
createWell(wallData) {
|
||||
let $this = this;
|
||||
if (this.viewer.terrainProvider._layers) {
|
||||
this.createBottomSurface(wallData.bottom_pos);
|
||||
let positions = Cesium.sampleTerrainMostDetailed(
|
||||
this.viewer.terrainProvider,
|
||||
wallData.lerp_pos
|
||||
);
|
||||
positions.then((pos) => {
|
||||
let positionList = [];
|
||||
for (let index = 0; index < pos.length; index++) {
|
||||
const element = pos[index];
|
||||
let curPos = Cesium.Cartesian3.fromRadians(
|
||||
element.longitude,
|
||||
element.latitude,
|
||||
element.height
|
||||
);
|
||||
positionList.push(curPos);
|
||||
}
|
||||
$this.createWellWall(wallData.bottom_pos, positionList);
|
||||
});
|
||||
} else {
|
||||
this.createBottomSurface(wallData.bottom_pos);
|
||||
this.createWellWall(wallData.bottom_pos, wallData.no_height_top);
|
||||
}
|
||||
}
|
||||
//坐标转换,转出经纬度格式
|
||||
ellipsoidToDegree(pos) {
|
||||
let cartesian3 = new Cesium.Cartesian3(pos.x, pos.y, pos.z);
|
||||
let cartographic =
|
||||
this.viewer.scene.globe.ellipsoid.cartesianToCartographic(cartesian3);
|
||||
return {
|
||||
longitude: Cesium.Math.toDegrees(cartographic.longitude),
|
||||
latitude: Cesium.Math.toDegrees(cartographic.latitude),
|
||||
altitude: cartographic.height,
|
||||
};
|
||||
}
|
||||
//创建地形开挖的底面对象
|
||||
createBottomSurface(points) {
|
||||
if (points.length) {
|
||||
let minHeight = this.getMinHeight(points);
|
||||
let positions = [];
|
||||
for (let i = 0; i < points.length; i++) {
|
||||
let curPoint = this.ellipsoidToDegree(points[i]);
|
||||
positions.push(curPoint.longitude, curPoint.latitude, minHeight);
|
||||
}
|
||||
let polygon = new Cesium.PolygonGeometry({
|
||||
polygonHierarchy: new Cesium.PolygonHierarchy(
|
||||
Cesium.Cartesian3.fromDegreesArrayHeights(positions)
|
||||
),
|
||||
perPositionHeight: true,
|
||||
});
|
||||
|
||||
let appearance = new Cesium.MaterialAppearance({
|
||||
translucent: false,
|
||||
flat: true,
|
||||
material: this.bottomMaterial,
|
||||
});
|
||||
this.bottomSurface = new Cesium.Primitive({
|
||||
geometryInstances: new Cesium.GeometryInstance({
|
||||
geometry: Cesium.PolygonGeometry.createGeometry(polygon),
|
||||
}),
|
||||
appearance: appearance,
|
||||
asynchronous: false,
|
||||
});
|
||||
ExcavationFaces.push(this.bottomSurface);
|
||||
this.viewer.scene.primitives.add(this.bottomSurface);
|
||||
}
|
||||
}
|
||||
// 创建地形开挖的侧面墙对象
|
||||
createWellWall(bottomPos, positionList) {
|
||||
let minHeight = this.getMinHeight(bottomPos);
|
||||
let maxHeights = [],
|
||||
minHeights = [];
|
||||
for (let i = 0; i < positionList.length; i++) {
|
||||
maxHeights.push(this.ellipsoidToDegree(positionList[i]).altitude);
|
||||
minHeights.push(minHeight);
|
||||
}
|
||||
let wall = new Cesium.WallGeometry({
|
||||
positions: positionList,
|
||||
maximumHeights: maxHeights,
|
||||
minimumHeights: minHeights,
|
||||
});
|
||||
let geometry = Cesium.WallGeometry.createGeometry(wall);
|
||||
let appearance = new Cesium.MaterialAppearance({
|
||||
translucent: false,
|
||||
flat: true,
|
||||
material: this.wallMaterial,
|
||||
});
|
||||
this.wellWall = new Cesium.Primitive({
|
||||
geometryInstances: new Cesium.GeometryInstance({
|
||||
geometry: geometry,
|
||||
attributes: {
|
||||
color: Cesium.ColorGeometryInstanceAttribute.fromColor(
|
||||
Cesium.Color.GREY
|
||||
),
|
||||
},
|
||||
id: "PitWall",
|
||||
}),
|
||||
appearance: appearance,
|
||||
asynchronous: false,
|
||||
});
|
||||
ExcavationFaces.push(this.wellWall);
|
||||
this.viewer.scene.primitives.add(this.wellWall);
|
||||
}
|
||||
//获取地形开挖最低点高程值
|
||||
getMinHeight(points) {
|
||||
let minHeight = 5000000;
|
||||
let minPoint = null;
|
||||
for (let i = 0; i < points.length; i++) {
|
||||
let height = points[i]["z"];
|
||||
if (height < minHeight) {
|
||||
minHeight = height;
|
||||
minPoint = this.ellipsoidToDegree(points[i]);
|
||||
}
|
||||
}
|
||||
return minPoint.altitude;
|
||||
}
|
||||
switchExcavate(show) {
|
||||
if (show) {
|
||||
this.viewer.scene.globe.material = null;
|
||||
this.wellWall.show = true;
|
||||
this.bottomSurface.show = true;
|
||||
} else {
|
||||
this.viewer.scene.globe.material = null;
|
||||
this.wellWall.show = false;
|
||||
this.bottomSurface.show = false;
|
||||
}
|
||||
}
|
||||
|
||||
updateExcavateDepth(height) {
|
||||
this.viewer.scene.primitives.remove(this.bottomSurface);
|
||||
this.viewer.scene.primitives.remove(this.wellWall);
|
||||
if (!this.wellData) {
|
||||
return
|
||||
}
|
||||
let lerp_pos = this.wellData.lerp_pos;
|
||||
let posList = [];
|
||||
for (let n = 0; n < lerp_pos.length; n++) {
|
||||
posList.push(
|
||||
Cesium.Cartesian3.fromRadians(
|
||||
lerp_pos[n].longitude,
|
||||
lerp_pos[n].latitude,
|
||||
this.excavateMinHeight - height
|
||||
)
|
||||
);
|
||||
}
|
||||
this.wellData.bottom_pos = posList;
|
||||
this.createWell(this.wellData);
|
||||
}
|
||||
}
|
||||
export default TerrainExcavation;
|
||||
54
src/Obj/Analysis/ViewShed/_element.js
Normal file
54
src/Obj/Analysis/ViewShed/_element.js
Normal file
@ -0,0 +1,54 @@
|
||||
function html() {
|
||||
return `
|
||||
<span class="custom-divider"></span>
|
||||
<div class="div-item">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<span class="label">位置拾取(起点、终点)</span>
|
||||
<button class="edit"><svg class="icon-edit"><use xlink:href="#yj-icon-edit"></use></svg>拾取</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="custom-divider"></span>
|
||||
<div class="div-item">
|
||||
<div class="row" style="margin-bottom: 25px;">
|
||||
<div class="col">
|
||||
<span class="label">视点高度</span>
|
||||
<div class="input-number input-number-unit-1">
|
||||
<input class="input" type="number" title="" min="0" max="999999" step="0.1" @model="viewPointHeight">
|
||||
<span class="unit">m</span>
|
||||
<span class="arrow"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row subtitle-box">
|
||||
<span class="subtitle">视域夹角</span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="range-box">
|
||||
<div class="range-bg">
|
||||
<div class="range-process-box">
|
||||
<div class="range-process"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="range-node-box">
|
||||
<span class="range-node-text">0°</span>
|
||||
<span class="range-node-text">45°</span>
|
||||
<span class="range-node-text">90°</span>
|
||||
<span class="range-node-text">135°</span>
|
||||
<span class="range-node-text">180°</span>
|
||||
<div class="range-node-active"><span class="range-node-active-text">0°</span></div>
|
||||
</div>
|
||||
<input type="range" max="180" min="0" step="1" name="horizontalViewAngle">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="custom-divider"></span>
|
||||
`
|
||||
}
|
||||
|
||||
export { html }
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user