diff --git a/.babelrc b/.babelrc deleted file mode 100644 index 89f4ba21..00000000 --- a/.babelrc +++ /dev/null @@ -1,10 +0,0 @@ -{ - "presets": [ - [ - "@babel/preset-env" - ] - ], - "plugins" : [ - "@babel/plugin-proposal-class-properties" - ] -} \ No newline at end of file diff --git a/.browserslistrc b/.browserslistrc deleted file mode 100644 index 214388fe..00000000 --- a/.browserslistrc +++ /dev/null @@ -1,3 +0,0 @@ -> 1% -last 2 versions -not dead diff --git a/.deepsource.toml b/.deepsource.toml deleted file mode 100644 index 02492c7b..00000000 --- a/.deepsource.toml +++ /dev/null @@ -1,22 +0,0 @@ -version = 1 - -test_patterns = [ - "tests/**", - "src/test/**" -] - -exclude_patterns = [ - "lib/**", - "orbit_bundle.js", - "public/**", - "cc/**" -] - -[[analyzers]] -name = "javascript" -enabled = true - - [analyzers.meta] - plugins = ["vue"] - - diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index b9a8d24d..00000000 --- a/.eslintrc.js +++ /dev/null @@ -1,48 +0,0 @@ -module.exports = { - env: { - browser: true, - es6: true, - node: true - }, - - globals: { - Atomics: "readonly", - SharedArrayBuffer: "readonly" - }, - - // Position is important, the last rules take precident here. For the least amount of prettier conficts with other eslint plugins. - // it has to come last - extends: ["eslint:recommended", "plugin:vue/recommended", "@vue/typescript", "prettier/vue"], - - parserOptions: { - ecmaVersion: 2018, - sourceType: "module", - parser: "@typescript-eslint/parser" - }, - - rules: { - "no-console": process.env.NODE_ENV === "production" ? "warn" : "off", - "no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off", - "linebreak-style": ["error", "unix"], - quotes: ["warn", "double"], - semi: ["warn", "always"], - "no-unused-vars": "off", - "no-case-declarations": "off", - "vue/max-attributes-per-line": "off", - "no-prototype-builtins": "off", - "space-before-function-paren": "off", - "no-useless-escape": "off", - "no-empty-pattern": "warn" - }, - - ignorePatterns: ["src/test/**", "tests/**", "**/examples/**", "**/parameterMenu.js", "src/assets/**"], - - overrides: [ - { - files: ["**/__tests__/*.{j,t}s?(x)", "**/tests/unit/**/*.spec.{j,t}s?(x)"], - env: { - mocha: true - } - } - ] -}; diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index cd2338b0..00000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: '' -labels: bug -assignees: '' - ---- - -**Describe the bug** -A clear and concise description of what the bug is. - -**To Reproduce** -Steps to reproduce the behavior: -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error - -Or add a GIF - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**Screenshots** -If applicable, add screenshots to help explain your problem. - -**Desktop (please complete the following information):** - - OS: [e.g. iOS] - - Browser [e.g. chrome, safari] - - Version [e.g. 22] - -**Additional context** -Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/custom.md b/.github/ISSUE_TEMPLATE/custom.md deleted file mode 100644 index 48d5f81f..00000000 --- a/.github/ISSUE_TEMPLATE/custom.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -name: Custom issue template -about: Describe this issue template's purpose here. -title: '' -labels: '' -assignees: '' - ---- - - diff --git a/.github/ISSUE_TEMPLATE/development-story.md b/.github/ISSUE_TEMPLATE/development-story.md deleted file mode 100644 index c1197c2a..00000000 --- a/.github/ISSUE_TEMPLATE/development-story.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -name: Development Story -about: Describe this issue template's purpose here. -title: "[Story]" -labels: '' -assignees: '' - ---- - -### Description - -(Concise Description of the issue) - -(Feature list) - -**Additional Description:** - -(Attach mockups and more information here) - -Acceptance Criteria: -- [ ] Unit Test -- [ ] ?? -- [ ] ?? -- [ ] ?? diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index bbcbbe7d..00000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project -title: '' -labels: '' -assignees: '' - ---- - -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. - -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. - -**Additional context** -Add any other context or screenshots about the feature request here. diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml deleted file mode 100644 index d56eff88..00000000 --- a/.github/workflows/main.yml +++ /dev/null @@ -1,65 +0,0 @@ -# This is a basic workflow to help you get started with Actions - -name: CI - -# Controls when the workflow will run -on: - # Triggers the workflow on push or pull request events but only for the master branch - push: - branches: [ webpack-build ] - pull_request: - branches: [ webpack-build ] - - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: - -# A workflow run is made up of one or more jobs that can run sequentially or in parallel -jobs: - lint: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - run : | - npm ci - npm run vue-lint - - lint-fix: - runs-on: ubuntu-latest - needs: [lint] - if: failure() - steps: - - name: Chckout the code - uses: actions/checkout@v2 - - name: Lint fix everything - run: | - npm ci - npm run vue-lint --fix - - name: commit and push changes - uses: devops-infra/action-commit-push@v0.3 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - commit_message: ran the lint fixer - - # This workflow contains a single job called "build" - build: - # The type of runner that the job will run on - runs-on: ubuntu-latest - needs: [lint] - - # Steps represent a sequence of tasks that will be executed as part of the job - steps: - # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@v2 - - # Runs a single command using the runners shell - - name: Run a one-line script - run: | - export NODE_OPTIONS=--openssl-legacy-provider - npm ci - npm run vue-build - - # Runs a set of commands using the runners shell - - name: Run a multi-line script - run: | - echo Add other actions to build, - echo test, and deploy your project. \ No newline at end of file diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 3c8cb3e0..00000000 --- a/.gitignore +++ /dev/null @@ -1,32 +0,0 @@ -__pycache__/ -*.py[cod] -*.stl - -coverage/ -node_modules/ - -old/*output -old/*.scad -*.log - -.idea/ -*tmp-browserify* - -3DuFapp.js -publish.sh - -docs/ -build/* -server-build/ - -# Folder view configuration files -.DS_Store -Desktop.ini - -# Thumbnail cache files -._* -Thumbs.db - -# Files that might appear on external disks -.Spotlight-V100 -.Trashes diff --git a/.nvmrc b/.nvmrc deleted file mode 100644 index 9a0c3d3f..00000000 --- a/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -v14.15.4 diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index 038d7af9..00000000 --- a/.prettierrc +++ /dev/null @@ -1,20 +0,0 @@ -{ - "arrowParens": "avoid", - "bracketSpacing": true, - "endOfLine": "lf", - "htmlWhitespaceSensitivity": "css", - "insertPragma": false, - "jsxBracketSameLine": false, - "jsxSingleQuote": false, - "printWidth": 180, - "proseWrap": "preserve", - "quoteProps": "as-needed", - "requirePragma": false, - "semi": true, - "singleQuote": false, - "tabWidth": 4, - "trailingComma": "none", - "useTabs": false, - "vueIndentScriptAndStyle": false, - "spacebeforefunctionparen": "never" -} diff --git a/.vscode/extensions.json b/.vscode/extensions.json deleted file mode 100644 index 096a8ec9..00000000 --- a/.vscode/extensions.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "recommendations": [ - "ms-vscode.vscode-typescript-next", - "oouo-diogo-perdigao.docthis", - "msjsdiag.debugger-for-chrome", - "octref.vetur", - "alefragnani.bookmarks", - "dzannotti.vscode-babel-coloring", - "ms-vsliveshare.vsliveshare-pack", - "redhat.vscode-yaml", - "yzhang.markdown-all-in-one", - "github.vscode-pull-request-github", - "streetsidesoftware.code-spell-checker", - "eamodio.gitlens", - "firefox-devtools.vscode-firefox-debug", - "jcbuisson.vue", - "dbaeumer.vscode-eslint", - "salbert.comment-ts" - ] -} diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index dae6ee06..00000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "type": "chrome", - "request": "launch", - "name": "vuejs: chrome", - "url": "http://localhost:8080", - "webRoot": "${workspaceFolder}/src", - "breakOnLoad": true, - "sourceMapPathOverrides": { - "webpack:///src/*": "${webRoot}/*" - } - }, - { - "type": "firefox", - "request": "launch", - "name": "vuejs: firefox", - "url": "http://localhost:8080", - "webRoot": "${workspaceFolder}/src", - "pathMappings": [ - { - "url": "webpack:///src/services/theme/utils.ts", - "path": "git:/Users/krishna/CIDAR/3duf-vue-port/src/cc/hardware/utils.ts?%7B%22path%22%3A%22%2FUsers%2Fkrishna%2FCIDAR%2F3duf-vue-port%2Fsrc%2Fcc%2Fhardware%2Futils.ts%22%2C%22ref%22%3A%22%22%7D" - }, - { - "url": "webpack:///src/", - "path": "${webRoot}/" - } - ] - } - ] -} diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index b3c804c4..00000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "files.eol": "\n", - "eslint.validate": ["vue", "html", "javascript", "typescript"], - "typescript.referencesCodeLens.enabled": true, - "typescript.updateImportsOnFileMove.enabled": "prompt", - "editor.defaultFormatter": "octref.vetur", - "editor.definitionLinkOpensInPeek": true, - "vetur.format.options.tabSize": 4, - "[typescript]": { - "editor.autoClosingBrackets": "languageDefined" - }, - "[typescriptreact]": { - "editor.autoClosingBrackets": "languageDefined" - }, - "[javascript]": { - "editor.autoClosingBrackets": "languageDefined" - }, - "[javascriptreact]": { - "editor.autoClosingBrackets": "languageDefined" - }, - "cSpell.words": ["registryref"], - "editor.codeActionsOnSave": { - "source.fixAll.eslint": "explicit" - }, - "rpc.enabled": true -} diff --git a/.vscode/workspace.code-workspace b/.vscode/workspace.code-workspace deleted file mode 100644 index 1d3ddb86..00000000 --- a/.vscode/workspace.code-workspace +++ /dev/null @@ -1,26 +0,0 @@ -{ - "folders": [ - { - "path": ".." - } - ], - "settings": { - "editor.formatOnSave": false, - "editor.tabSize": 4, - "editor.insertSpaces": true, - "editor.detectIndentation": false, - "editor.defaultFormatter": null, - "editor.codeActionsOnSave": { - "source.fixAll.eslint": true - }, - "eslint.alwaysShowStatus": true, - "eslint.codeActionsOnSave.mode": "all", - "eslint.codeAction.showDocumentation": { - "enable": true - }, - "eslint.lintTask.enable": true, - "javascript.format.enable": false, - "typescript.format.enable": false, - "vetur.validation.template": false - } -} diff --git a/CNAME b/CNAME deleted file mode 100644 index 9a194389..00000000 --- a/CNAME +++ /dev/null @@ -1 +0,0 @@ -3duf.org \ No newline at end of file diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md deleted file mode 100644 index 139189b2..00000000 --- a/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,76 +0,0 @@ -# Contributor Covenant Code of Conduct - -## Our Pledge - -In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our project and -our community a harassment-free experience for everyone, regardless of age, body -size, disability, ethnicity, sex characteristics, gender identity and expression, -level of experience, education, socio-economic status, nationality, personal -appearance, race, religion, or sexual identity and orientation. - -## Our Standards - -Examples of behavior that contributes to creating a positive environment -include: - -- Using welcoming and inclusive language -- Being respectful of differing viewpoints and experiences -- Gracefully accepting constructive criticism -- Focusing on what is best for the community -- Showing empathy towards other community members - -Examples of unacceptable behavior by participants include: - -- The use of sexualized language or imagery and unwelcome sexual attention or - advances -- Trolling, insulting/derogatory comments, and personal or political attacks -- Public or private harassment -- Publishing others' private information, such as a physical or electronic - address, without explicit permission -- Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Our Responsibilities - -Project maintainers are responsible for clarifying the standards of acceptable -behavior and are expected to take appropriate and fair corrective action in -response to any instances of unacceptable behavior. - -Project maintainers have the right and responsibility to remove, edit, or -reject comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct, or to ban temporarily or -permanently any contributor for other behaviors that they deem inappropriate, -threatening, offensive, or harmful. - -## Scope - -This Code of Conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. Examples of -representing a project or community include using an official project e-mail -address, posting via an official social media account, or acting as an appointed -representative at an online or offline event. Representation of a project may be -further defined and clarified by project maintainers. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team at rkrishnasanka@gmail.com. All -complaints will be reviewed and investigated and will result in a response that -is deemed necessary and appropriate to the circumstances. The project team is -obligated to maintain confidentiality with regard to the reporter of an incident. -Further details of specific enforcement policies may be posted separately. - -Project maintainers who do not follow or enforce the Code of Conduct in good -faith may face temporary or permanent repercussions as determined by other -members of the project's leadership. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html - -[homepage]: https://www.contributor-covenant.org - -For answers to common questions about this code of conduct, see -https://www.contributor-covenant.org/faq diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index caa73ae8..00000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,92 +0,0 @@ -# Contributing - -When contributing to this repository, please first discuss the change you wish to make via issue, -email, or any other method with the owners of this repository before making a change. - -Please note we have a code of conduct, please follow it in all your interactions with the project. - -## Pull Request Process - -1. Ensure any install or build dependencies are removed before the end of the layer when doing a - build. -2. Update the README.md with details of changes to the interface, this includes new environment - variables, exposed ports, useful file locations and container parameters. -3. Increase the version numbers in any examples files and the README.md to the new version that this - Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/). -4. You may merge the Pull Request in once you have the sign-off of two other developers, or if you - do not have permission to do that, you may request the second reviewer to merge it for you. - -## Code of Conduct - -### Our Pledge - -In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our project and -our community a harassment-free experience for everyone, regardless of age, body -size, disability, ethnicity, gender identity and expression, level of experience, -nationality, personal appearance, race, religion, or sexual identity and -orientation. - -### Our Standards - -Examples of behavior that contributes to creating a positive environment -include: - -- Using welcoming and inclusive language -- Being respectful of differing viewpoints and experiences -- Gracefully accepting constructive criticism -- Focusing on what is best for the community -- Showing empathy towards other community members - -Examples of unacceptable behavior by participants include: - -- The use of sexualized language or imagery and unwelcome sexual attention or - advances -- Trolling, insulting/derogatory comments, and personal or political attacks -- Public or private harassment -- Publishing others' private information, such as a physical or electronic - address, without explicit permission -- Other conduct which could reasonably be considered inappropriate in a - professional setting - -### Our Responsibilities - -Project maintainers are responsible for clarifying the standards of acceptable -behavior and are expected to take appropriate and fair corrective action in -response to any instances of unacceptable behavior. - -Project maintainers have the right and responsibility to remove, edit, or -reject comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct, or to ban temporarily or -permanently any contributor for other behaviors that they deem inappropriate, -threatening, offensive, or harmful. - -### Scope - -This Code of Conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. Examples of -representing a project or community include using an official project e-mail -address, posting via an official social media account, or acting as an appointed -representative at an online or offline event. Representation of a project may be -further defined and clarified by project maintainers. - -### Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team at [INSERT EMAIL ADDRESS]. All -complaints will be reviewed and investigated and will result in a response that -is deemed necessary and appropriate to the circumstances. The project team is -obligated to maintain confidentiality with regard to the reporter of an incident. -Further details of specific enforcement policies may be posted separately. - -Project maintainers who do not follow or enforce the Code of Conduct in good -faith may face temporary or permanent repercussions as determined by other -members of the project's leadership. - -### Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at [http://contributor-covenant.org/version/1/4][version] - -[homepage]: http://contributor-covenant.org -[version]: http://contributor-covenant.org/version/1/4/ diff --git a/InsertTextDialog.vue.txt b/InsertTextDialog.vue.txt deleted file mode 100644 index cfa3c89e..00000000 --- a/InsertTextDialog.vue.txt +++ /dev/null @@ -1,70 +0,0 @@ - - diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 3bf17a17..00000000 --- a/LICENSE +++ /dev/null @@ -1,25 +0,0 @@ -BSD 2-Clause License - -Copyright (c) 2019, CIDAR LAB -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md deleted file mode 100644 index 40dc7576..00000000 --- a/README.md +++ /dev/null @@ -1,107 +0,0 @@ - - -An Interactive Design Tool for Continuous Flow Microfluidic Devices - [3DuF.org](http://3duf.org) - -## Status - -[![Netlify Status](https://api.netlify.com/api/v1/badges/01675390-381f-45a9-88b1-a6f8db0fecbc/deploy-status)](https://app.netlify.com/sites/wonderful-blackwell-a043b5/deploys) - -## About - -The design of microfluidic Lab on a Chip (LoC) systems is an onerous task requiring specialized skills in fluid dynamics, mechanical design drafting, and manufacturing. Engineers face significant challenges during the labor-intensive process of designing microfluidic devices, with very few specialized tools that help automate the process. Typical design iterations require the engineer to research the architecture, manually draft the device layout, optimize for manufacturing processes and manually calculate and program the valve sequences that operate the microfluidic device. The problem compounds when the devices are intended for executing biological assays where engineers not only have to test the functionality of the chip but are also required to optimize them for robust performance. In this paper, we present an interactive tool for designing continuous flow microfluidic devices. 3DuF is the first completely open-source interactive microfluidic system designer that readily supports state-of-the-art design automation algorithms. Through various case studies, we show 3DuF can be used to reproduce designs from literature, provide metrics for evaluating microfluidic design complexity and showcase how 3DuF is a platform for integrating a wide assortment of engineering techniques used in the design of microfluidic devices as a part of the standard design work-flow. - -## Academic Publications - -> Sanka, Radhakrishna, Joshua Lippai, Dinithi Samarasekera, Sarah Nemsick, and Douglas Densmore. “3DμF - Interactive Design Environment for Continuous Flow Microfluidic Devices.” Scientific Reports 9, no. 1 (December 2019). - -[https://doi.org/10.1038/s41598-019-45623-z](https://doi.org/10.1038/s41598-019-45623-z) - -## Usage - -### Design Environment - - - -### Keyboard Shortcuts - -- Pan Canvas: `middle mouse button` and `arrow` keys -- Reset Canvas View: `F` key -- Activate Select Tool/ Deselect Selected Components: `Esc` -- Activate Component Copy Mode: `ctrl+C` -\> `ctrl+V` -- Undo Last Edit: `ctrl+Z` -- Select All: `ctrl+A` -- Save JSON file: ` ctrl+ S` - -### Installation and Debugging - -[Instructions for installation, build, and test are in the wiki.](https://github.com/CIDARLAB/3DuF/wiki/Building-and-Testing-3DuF) - -### Selecting and Configuring Feature Types - -Use the buttons in the menu (on the left) to select a feature type to place. -The gear-shaped button will bring up a menu that will allow you to adjust the parameters for that feature type. - -Click on a layer to select it. This will cause new features to be placed only into that layer. The currently-selected layer's color will be reflected in the button color of any selected feature. - -### Placing Features - -Left click on the device canvas (on the right) to place a feature. Some features (such as Channels and Chambers) are determined by two points, and are placed by clicking and dragging. - -Right click on a feature to select it. Right click and drag to select multiple features at once. - -If a layer has been selected, only features on that layer can be selected this way. - -### Editing Features - -Left click on any selected feature to bring up a dialog box which will allow you to edit its parameters. If more than one feature is selected, parameters will be inherited by all currently selected features of the same type as the one you clicked. - -### Saving Designs - -Under `Save` in the main menu, click a to download the current design in the selected format. - -### Loading Designs - -After saving a device design to JSON, drag and drop it from your computer onto the device canvas to load it. - -## Component Library - - - - -## Primitives Server - -As 3DuF continues to become a core component of the Microfluidics CAD Ecossytem, we have incorporated the ability to generate component dimensions, port locations, default dimensions for all the parametrically generated components supported by 3DuF. - -The instructions for starting this server are as follows: -``` -docker build -f primitives-server.Dockerfile -t primitives-server:latest . -docker run -p 6060:6060 primitives-server -``` - -This will enable the API on port 6060. This can be verified by either going to `http://localhost:6060` or by running the following command: - -``` -curl http://localhost:6060 -``` - -Alternatively you can install the dev version of the library if you want to debug it locally. - -``` -npm ci -cd src/server -npm ci -npm run dev -``` - -## Attributions - -Error Logging and Tracking enabled by [TrackJS](https://trackjs.com/) - -## License - -BSD 2-Clause License - -Copyright (c) 2019, CIDAR LAB -All rights reserved. - -See [LICENSE](/LICENSE) for more information. diff --git a/dist/animations.css b/animations.css similarity index 100% rename from dist/animations.css rename to animations.css diff --git a/cc/legacy-neptune-control-code/DispenserCommands.js b/cc/legacy-neptune-control-code/DispenserCommands.js deleted file mode 100644 index 09da0fa1..00000000 --- a/cc/legacy-neptune-control-code/DispenserCommands.js +++ /dev/null @@ -1,221 +0,0 @@ -/** - * Created by rebeccawolf on 10/5/16. - */ - -function incrementDispenserPosition(dispenser_to_control) { - // identify which dispenser you are sending command to - localStorage.dispenserToControl = dispenser_to_control; - // see if already maxed out at highest position - if ( - parseFloat(JSON.parse(localStorage.dispenserData)[dispenser_to_control - 1]["Current_State"]) <= - parseFloat(JSON.parse(localStorage.dispenserData)[dispenser_to_control - 1]["Max"]) - ) { - var conversionTable = JSON.parse(JSON.parse(localStorage.getItem("dispenserConversions"))[dispenser_to_control]); // conversion table for specific dispenser you are controlling - - var temp = JSON.parse(localStorage.dispenserData); - var index = parseFloat(temp[dispenser_to_control - 1]["Current_State"]); // current uL state - // var PWMcurrent = conversionTable[index]; // find the PWM value which corresponds to the mL value chosen to send to arduino - var foundIndex = false; - var nextuL = 0; - var nextPWM = 0; - // figure out which is the next increment of uL value we can dispenser from the conversion table - for (var uL = 0; uL <= conversionTable.length; uL = uL + 2) { - if (foundIndex == true) { - nextuL = conversionTable[uL]; // note the next uL value to send - nextPWM = conversionTable[uL + 1]; - break; - } - if (conversionTable[uL] == index) { - foundIndex = true; - } - if (conversionTable[uL] > index) { - // surpassed current value, send this one!! - nextuL = conversionTable[uL]; - nextPWM = conversionTable[uL + 1]; - break; - } - } - nextPWM = nextPWM.toFixed(0); - - // set current state to one which corresponds to a value in conversion table - temp[dispenser_to_control - 1]["Current_State"] = nextuL.toString(); - localStorage.dispenserData = JSON.stringify(temp); - - sendCommandDispense(nextPWM, dispenser_to_control); - updateDispenseProgressBar(dispenser_to_control); - } else { - toastr.warning("You have already dispensed the full amount of this syringe."); - } - return false; -} - -function decrementDispenserPosition(dispenser_to_control) { - localStorage.dispenserToControl = dispenser_to_control; - // assumes the capacity of the syringe is 9 mL - if ( - parseFloat(JSON.parse(localStorage.dispenserData)[dispenser_to_control - 1]["Current_State"]) > - parseFloat(JSON.parse(localStorage.dispenserData)[dispenser_to_control - 1]["Min"]) - ) { - var conversionTable = JSON.parse(JSON.parse(localStorage.getItem("dispenserConversions"))[dispenser_to_control]); // conversion table for specific dispenser you are controlling - - var temp = JSON.parse(localStorage.dispenserData); - var index = parseFloat(temp[dispenser_to_control - 1]["Current_State"]); // current uL state - var foundIndex = false; - var nextuL = 0; - var nextPWM = 0; - - // figure out which is the next increment of uL value we can dispenser from the conversion table - for (var uL = conversionTable.length - 2; uL >= 0; uL = uL - 2) { - if (foundIndex == true) { - nextuL = conversionTable[uL]; // note the next uL value to send - nextPWM = conversionTable[uL + 1]; - break; - } - if (conversionTable[uL] == index) { - foundIndex = true; - } - if (conversionTable[uL] < index) { - // surpassed current value, send this one!! - nextuL = conversionTable[uL]; - nextPWM = conversionTable[uL + 1]; - break; - } - } - nextPWM = nextPWM.toFixed(0); - - // set current state to one which corresponds to a value in conversion table - temp[dispenser_to_control - 1]["Current_State"] = nextuL.toString(); - localStorage.dispenserData = JSON.stringify(temp); - - sendCommandDispense(nextPWM, dispenser_to_control); - updateDispenseProgressBar(dispenser_to_control); - } else { - toastr.warning("You have reached minimum volume capacity."); - } - return false; -} - -function wrap_data_for_Arduino_Dispense(PWM, dispenser_to_control) { - // var dispenser_to_control = localStorage.dispenserToControl; - var temp = JSON.parse(localStorage.dispenserData); - var deviceNum = temp[dispenser_to_control - 1]["deviceIndex"]; - console.log("the device num is: " + deviceNum); - - // FIRST, PAD VALUES WITH 0's SUCH THAT THE VALUE IS 3 CHARACTERS LONG - var dispenser_to_control_padded = zeroFill(deviceNum, 4); - var PWMval_padded = zeroFill(PWM, 4); - // CONCAT THE VALVE NUMBER AND PWM VALUE - var pre_command = dispenser_to_control_padded.concat(PWMval_padded); - // ADD A START CODON TO SIGNIFY THE BEGINING OF SIGNAL - var startStr = ""; - var pre_command_s = startStr.concat(pre_command); - // ADD A STOP CODON TO SIGNIFY THE END OF SIGNAL - var command = pre_command_s.concat("\n"); - // RETURN THE DATA - return command; -} -function sendCommandDispense(PWM, dispenser_to_control) { - var command = wrap_data_for_Arduino_Dispense(PWM, dispenser_to_control); - var message = "Sending to Arduino: "; - var command_info = message.concat(command); - // --- Include code to serial.write() the command to the Arduino here --- // - toastr.info(command_info); - // writeToSerialConsole(command_info); - // console.log(command); - localStorage.setItem("myCommand", command); - $.ajax({ - url: "/serialcommunication/send", - type: "POST", - async: true, - data: { - commandData: command - }, - success: function(response) {}, - error: function(response) {} - }); -} -// ./ END DISPENSER FUNCTIONS - -// HELPER FUNCTIONS FOR SENDING COMMANDS FOR BOTH VALVES AND DISPENSERS -function zeroFill(number, width) { - width -= number.toString().length; - if (width > 0) { - return new Array(width + (/\./.test(number) ? 2 : 1)).join("0") + number; - } - return number + ""; // always return a string -} -function paddy(n, p, c) { - var pad_char = typeof c !== "undefined" ? c : "0"; - var pad = new Array(1 + p).join(pad_char); - return (pad + n).slice(-pad.length); -} - -// ./ END HELPER FUNCTIONS - -// dispenser arrow key functionality -function upArrow() { - if (JSON.parse(localStorage.dispenserData)[localStorage.dispenserToControl - 1]["orientation"] === "pull") { - incrementDispenserPosition(localStorage.dispenserToControl); // output fluid for pull syringe = move syringe to higher position - } else { - decrementDispenserPosition(localStorage.dispenserToControl); // output fluid for push syringe = move syringe to lower position - } - return false; -} -function downArrow() { - if (JSON.parse(localStorage.dispenserData)[localStorage.dispenserToControl - 1]["orientation"] === "pull") { - decrementDispenserPosition(localStorage.dispenserToControl); // retract fluid for pull syringe = move syringe to lower position - } else { - incrementDispenserPosition(localStorage.dispenserToControl); // retract fluid for push syringe = move syringe to higher position - } - return false; -} -function dispenseSelected(down) { - switch (down.keyCode) { - case 38: // up key - if (localStorage.activeDispenser != "none") { - upArrow(); - } - break; - case 40: // down key - if (localStorage.activeDispenser != "none") { - downArrow(); - } - break; - } -} -// ./ end dispenser arrow key functionality - -// dispenser modal progress bar update -function updateDispenseProgressBar(dispenserIDNum) { - currentState = JSON.parse(localStorage.dispenserData)[dispenserIDNum - 1]["Current_State"]; - maxVol = JSON.parse(localStorage.dispenserData)[dispenserIDNum - 1]["Max"]; - minVol = JSON.parse(localStorage.dispenserData)[dispenserIDNum - 1]["Min"]; - if (currentState == 0) { - percentageUpdate = 0; // value is NaN otherwise - } else { - percentageUpdate = Math.floor(((currentState - minVol) / (maxVol - minVol)) * 100); - } - - // first update syringe - updateDispenseSyringe(dispenserIDNum, percentageUpdate); - - // now base percentage update on syringe orientation: - if (JSON.parse(localStorage.dispenserData)[dispenserIDNum - 1]["orientation"] === "push") { - percentageUpdate = 100 - percentageUpdate; - } - - document.getElementById("progress" + dispenserIDNum).innerHTML = percentageUpdate + "% total vol"; - document.getElementById("stateOf" + dispenserIDNum).innerHTML = currentState + " uL"; - $("#progress" + dispenserIDNum) - .css("width", percentageUpdate + "%") - .attr("aria-valuenow", percentageUpdate); - return false; -} - -// update dispenserUI modal syringe to dispensed value -function updateDispenseSyringe(dispenserIDNum, percentUpdate) { - // min/max displacement for syringe is 92 - 40 = 52 - var zeroDisplacement = (percentUpdate / 100) * 52; - var displacement = zeroDisplacement + 40; - $("#plunger" + dispenserIDNum).css("left", displacement + "px"); -} diff --git a/cc/legacy-neptune-control-code/EqualFlowRateInit.js b/cc/legacy-neptune-control-code/EqualFlowRateInit.js deleted file mode 100644 index ab9499c9..00000000 --- a/cc/legacy-neptune-control-code/EqualFlowRateInit.js +++ /dev/null @@ -1,243 +0,0 @@ -/** - * Created by rebeccawolf on 8/30/16. equal Flow rate - */ - -/* Create uL_table - - */ -var theta_max = 157.0; -var theta_min = -13.6; -var r = 0.75; -var b = 3; -var d = 0.88; -var a = 0.25; -var PWM_min = 180; -var PWM_max = 500; -var X_min = 2.071; -var mL_max = 6.23; -var X_max = 3.645; -var mL_min = 0; - -var mL_range = mL_max - mL_min; - -function PWM2rad(PWM) { - var deg = ((PWM - PWM_min) * (theta_max - theta_min)) / (PWM_max - PWM_min) + theta_min; - return deg * (Math.PI / 180); -} - -var create_uL_table = function(uL_precision) { - var uL_min = mL_min * 1000; // convert incoming variables from mL to uL - var uL_range = mL_range * 1000; // convert incoming variables from mL to uL - - // Create PWM_table - var PWM_table = []; - for (var i = PWM_min; i <= PWM_max; i++) { - // From PWM_min value to PWM_max value - PWM_table.push(i); // Add current PWM value to PWM_table - var mL_temp = mL_max - (r * Math.cos(PWM2rad(i)) + Math.sqrt(Math.pow(b, 2) - Math.pow(r * Math.sin(PWM2rad(i)) + d, 2)) - X_min) / a; // Calculate mL value with formula of motion - var uL_temp = Math.round(mL_temp * 10000) / 10; // convert to uL and round to first decimal place - PWM_table.push(uL_temp); // Add uL value to PWM_table - } - - // create uL_table - var uL_table = []; - // create conversion tables - var conversion_table = {}; - for (var i = uL_min; i < uL_range + uL_min + uL_precision; i = i + uL_precision) { - // From uL_min (a given) to uL_min+uL_range! uL_precision added on to allow last uL value to be iterated through. Increase by steps of uL_precision - // rename i (which is current uL value) - var uL_current = i; // rename i to something more readable - uL_current = Math.round(uL_current * 100) / 100; // round to 2 decimal places - - uL_table.push(uL_current); // Add the current uL value to uL_table - - // Find PWM values - - // Add First PWM value, matched easily - if (i == uL_min) { - // We know the first value, which can't be found with linear interpolation - uL_table.push(PWM_table[0]); - conversion_table[uL_min] = PWM_table[0]; - continue; - } - // Linear interpolation to find other PWM values - // Skip to 2nd value as we already logged the first - for (var j = 3; j <= PWM_table.length; j = j + 2) { - // Iterate through uL values in PWM_table (start at 2nd uL value, index 3. Go length of PWM table. Increase by 2 to avoid looking at PWM values) - if (PWM_table[j] >= uL_current && j % 2 > 0) { - // If uL value in PWM_table is greater than or equal to our current uL value, find PWM inbetween PWMs in PWM_table - var PWM_between = PWM_table[j - 3] + (uL_current - PWM_table[j - 2]) * ((PWM_table[j - 1] - PWM_table[j - 3]) / (PWM_table[j] - PWM_table[j - 2])); // Find PWM value via linear interpolation - var PWM_between = Math.round(PWM_between * 100) / 100; // Round calculated PWM value to 2 decimal places - uL_table.push(PWM_between); // Add calculated PWM value to table - conversion_table[uL_current] = PWM_between; - break; - } - } - } - uL_table.push(PWM_max); // Add last PWM value, not calculated above with linear interpolation - - return { - PWM_table: PWM_table, // Return PWM_table - uL_table: uL_table, // Return uL_table - conversion_table: conversion_table // Return table to convert PWM to uL - }; -}; - -/* Calculate even uL steps - - Discription: - At any arbitrary position, move to any other position in - equal fluid dispensing steps over a set amount of time - - Inputs: - Pump number - uL_table - PWM_table - highest uL difference - Current uL value - Goal uL value - Time to get from current to goal uL value - Outputs: - Serial command to Arduino 5x per second in format '00010300' with 0001 being the pump number and 0300 being the PWM value to go to - */ - -/*PWM_table - Array of PWM values, uL values = [ - 180 PWM, 0 uL, - 181 PWM, 1.14 uL, - 182 PWM, 2.52 uL - ] - - uL_table (ordered ) - Array of uL values, PWM values = [ - 0 uL, 180 PWM, - 0.5 uL, 180.45 PWM, - 1 uL, 181.2 PWM - ] - */ - -/* Example inputs: - Pump number = 1 - uL_table = maping_table - PWM_table = PWM_table - highest uL difference = 1.5 uL - Current uL value = 12 uL - Goal uL value = 400 uL - Time to get from current to goal uL values = 5 seconds - */ - -function even_uL_steps(uL_table, PWM_table, uL_precision, current_uL, goal_uL, time_sec) { - // Get uL_to_dispense - var uL_to_dispense = Math.abs(goal_uL - current_uL); - - // Get Total number of steps - var num_steps = uL_to_dispense / uL_precision; - - // Get number of steps per second and number of seconds per step - var steps_per_second = num_steps / time_sec; // send to user, not used in program - var seconds_per_step = time_sec / num_steps; // needed for delay between step - - // Find current place and goal place in uL_table - var f_found = false; // set to true when the first_uL_index is found to avoid this if statment through rest of loop - var going_up_uL = goal_uL - current_uL > 0; - - var conversion_table = {}; - - if (going_up_uL) { - // if increasing in uL from current_uL to goal_uL - for (var i = 0; i < uL_table.length; i = i + 2) { - // From 0 through length of uL_table in steps of 2, hitting just uL values - if (uL_table[i] >= current_uL && f_found == false) { - // If uL value in uL_table is greater than or equal to our current_uL (and the first_uL_index has not been found yet) - var first_uL_index = i; // log index of where the uL_currently is in uL_table (logs the uL value directly above or equal to it) - f_found = true; // indicate we found the first uL_index - } - if (uL_table[i] >= goal_uL) { - // If uL value in uL_table is greater than or equal to our goal_uL - var goal_uL_index = i; // log index of where the uL_goal is in the uL_table (logs the uL value directly above or equal to it) - break; // Stop for loop, we have the info we need - } - } - } else { - // if decreasing in uL from current_uL to goal_uL - for (var i = uL_table.length - 2; i >= 0; i = i - 2) { - // From length of uL_table through 0 in steps of 2, hitting just uL values - if (uL_table[i] <= current_uL && f_found == false) { - // If uL value in uL_table is less than or equal to our current_uL (and the first_uL_index has not been found yet) - var first_uL_index = i; // log index of where the uL_currently is in uL_table (logs the uL value directly above or equal to it) - f_found = true; // indicate we found the first uL_index - } - if (uL_table[i] <= goal_uL) { - // If uL value in uL_table is greater than or equal to our goal_uL - var goal_uL_index = i; // log index of where the uL_goal is in the uL_table (logs the uL value directly above or equal to it) - break; // Stop for loop, we have the info we need - } - } - } - - //////////////////////////////////////////////////////////// - - // Iterate through uL_table from next uL_index and go specified number of steps - // MUST DELAY each console.log by the variable 'seconds_per_step' - var PWM_values = []; // Used to keep track of PWM steps to move, for record keeping and debugging - if (going_up_uL) { - // if increasing in uL from current_uL to goal_uL - for (var i = first_uL_index; i <= goal_uL_index; i = i + 2) { - // From our current uL index in uL_table to goal index in uL_table - // if last step - if (i == goal_uL_index) { - // If last step - if (Math.abs(uL_table[i] - goal_uL) < Math.abs(uL_table[i - 2] - goal_uL)) { - // if this uL value from uL_table is closer to goal_uL than the previous one - var end_PWM = Math.round(uL_table[i + 1]); // used for PWM tracking - PWM_values.push(Math.round(uL_table[i + 1])); // Add rounded PWM value to PWM_values list for record keeping and debugging - conversion_table[Math.round(uL_table[i + 1])] = uL_table[i]; - //console.log(end_PWM); //////////// Send pump number and rounded PWM value to arduino - } else { - var end_PWM = Math.round(uL_table[i - 1]); // used for PWM tracking - } - } - // If normal step - else { - // Normal indexes - //console.log(Math.round(uL_table[i+1])); /////////// Send pump number and rounded PWM value to arduino - PWM_values.push(Math.round(uL_table[i + 1])); // Add rounded PWM value to PWM_values list for record keeping and debugging - conversion_table[Math.round(uL_table[i + 1])] = uL_table[i]; - } - } - } else { - // if decreasing in uL from current_uL to goal_uL - for (var i = first_uL_index; i >= goal_uL_index; i = i - 2) { - // From our current uL index in uL_table to goal index in uL_table - // if last step - if (i == goal_uL_index) { - // If last step - if (Math.abs(uL_table[i] - goal_uL) < Math.abs(uL_table[i + 2] - goal_uL)) { - // if this uL value from uL_table is closer to goal_uL than the previous one - var end_PWM = Math.round(uL_table[i + 1]); // used for PWM tracking - PWM_values.push(Math.round(uL_table[i + 1])); // Add rounded PWM value to PWM_values list for record keeping and debugging - conversion_table[Math.round(uL_table[i + 1])] = uL_table[i]; - //console.log(end_PWM); //////////// Send pump number and rounded PWM value to arduino - } else { - var end_PWM = Math.round(uL_table[i + 3]); // used for PWM tracking - } - } - // If normal step - else { - // Normal indexes - //console.log(Math.round(uL_table[i+1])); /////////// Send pump number and rounded PWM value to arduino - PWM_values.push(Math.round(uL_table[i + 1])); // Add rounded PWM value to PWM_values list for record keeping and debugging - conversion_table[Math.round(uL_table[i + 1])] = uL_table[i]; - } - } - } - - console.log("command conversion table: "); - console.log(conversion_table); - - return { - PWM_values: PWM_values, // Return PWM_table - seconds_per_step: seconds_per_step, // Return uL_table - conversion_table: conversion_table // Return table to convert PWM to uL - }; -} diff --git a/cc/legacy-neptune-control-code/JSONValveDispenserLoad.js b/cc/legacy-neptune-control-code/JSONValveDispenserLoad.js deleted file mode 100644 index d89d0c5d..00000000 --- a/cc/legacy-neptune-control-code/JSONValveDispenserLoad.js +++ /dev/null @@ -1,184 +0,0 @@ -/** - * Created by rebeccawolf on 7/26/16. - */ - -// Parsing JSON to look for control features (valves and dispensers); load information into global variables -function loadButtons() { - // load file for parsing used for counting and locating buttons - var json = defaultJSON; - console.log("found the loadButtons function: "); - console.log(json); - for (var i = 0; i < json.layers.length; i++) { - if (json.layers[i].name === "control") { - controlOnly = JSON.stringify(json.layers[i].features); - } - if (json.layers[i].name === "flow") { - flowOnly = JSON.stringify(json.layers[i].features); - } - } - - // Use Json as a string - var jsonString = JSON.stringify(json); - - // Now look for all Port in the control layer only - var Re = /Port.+?\[(.+?),(.+?)\].+?/g; - var myArray; - var portArray = []; - var portX = []; - var portY = []; - - // look through control layer for ports - while ((myArray = Re.exec(controlOnly)) !== null) { - portX.push(myArray[1]); - portY.push(myArray[2]); - portArray.push(myArray.index); - } - - // Store json variables to localStorage in form of JSON object... - localStorage.portXcoords = JSON.stringify(portX); - localStorage.portYcoords = JSON.stringify(portY); - - // Now look for all Ports (Dispensers) in the control layer only - var myArrayDisp; - var portArrayDisp = []; - var portXDisp = []; - var portYDisp = []; - - // look through flow layer for ports - while ((myArrayDisp = Re.exec(flowOnly)) !== null) { - portXDisp.push(myArrayDisp[1]); - // console.log("should be x coord in flow layer: " + myArrayDisp[1]); - portYDisp.push(myArrayDisp[2]); - portArrayDisp.push(myArrayDisp.index); - } - - // Store json variables to localStorage in form of JSON object... - localStorage.portXcoordyessDisp = JSON.stringify(portXDisp); - localStorage.portYcoordsDisp = JSON.stringify(portYDisp); -} - -// after parsing JSON we can create instances of HTML templates to place over canvas -function placeButtons() { - var canvasZoom = paper.view.zoom; - - // for each pump, create new instance of valve template - for (var i = 0; i < JSON.parse(localStorage.getItem("portXcoords")).length; i++) { - var content = $("#content"); - var template = document.getElementById("valve-template").content.cloneNode(true); - var valveDiv = template.querySelector(".valve"); - - valveDiv.style.position = "absolute"; - - valveDiv.style.top = (parseInt(JSON.parse(localStorage.portYcoords)[i]) - paper.view.bounds.topLeft["_y"]) * canvasZoom + 1.25 * Math.pow(canvasZoom * 5, 5) + "px"; - valveDiv.style.left = (parseInt(JSON.parse(localStorage.portXcoords)[i]) - paper.view.bounds.topLeft["_x"]) * canvasZoom + 1.25 * Math.pow(canvasZoom * 5, 5) + "px"; - - var specificImage = template.querySelector(".valve_color"); - // set id of each valve anchor based on location in array - specificImage.id = "valve" + (i + 1); - // assign appropriate valve marker based on state - specificImage.onclick = onclickanchortag; - if (JSON.parse(localStorage.pumpData)[i]["Current_State"] === "closed") { - specificImage.src = "../images/fluigi/valveMarkerClosed.svg"; - } else { - specificImage.src = "../images/fluigi/valveMarkerOpen.svg"; - } - - valveButton = template.querySelector(".valve"); - - var valveIDLabel = template.querySelector(".IDtext"); - valveIDLabel.textContent = i + 1; - if (i + 1 > 9) { - template.querySelector(".IDtext").style = "padding-left: 9px"; - } - - content.append(template); - } - - // for each DISPENSER, create new instance of DISPENSER template - for (var i = 0; i < JSON.parse(localStorage.getItem("portXcoordsDisp")).length; i++) { - var content = $("#content"); - - // create new dispenser instance - var template = document.getElementById("dispenser-template").content.cloneNode(true); - var valveDiv = template.querySelector(".valve"); - var modalDiv = template.querySelector(".dispenserModalClass"); - var gottaCatchEmAll = template.querySelector(".catchDispenser"); - var progress = template.querySelector(".progress-bar"); - var currentStateTxt = template.querySelector(".currentStateModalVal"); - var form = template.querySelector(".dispenseRate"); - var sendDispense = template.querySelector(".sendDispense"); - var dispenseVol = template.querySelector(".dispenseVol"); - var dispenseTime = template.querySelector(".dispenseTime"); - var plunger = template.querySelector(".syringePlunger"); - var orientation = template.querySelector(".orientationBtn"); - - valveDiv.style.position = "absolute"; - - // +220 bc canvas is positioned 220px from top & -20 so that valve is positioned from center of circle - var yCoord = (parseInt(JSON.parse(localStorage.portYcoordsDisp)[i]) - paper.view.bounds.topLeft["_y"]) * canvasZoom + 1.25 * Math.pow(canvasZoom * 5, 5); - var xCoord = (parseInt(JSON.parse(localStorage.portXcoordsDisp)[i]) - paper.view.bounds.topLeft["_x"]) * canvasZoom + 1.25 * Math.pow(canvasZoom * 5, 5); - - modalDiv.id = "dispenserModal" + (i + 1); - var modalID = template.querySelector("#dispenserModal" + (i + 1)); - - progress.id = "progress" + (i + 1); - - currentStateTxt.id = "stateOf" + (i + 1); - - // style position of dispenser modal - if (xCoord + 400 > $(window).width()) { - modalID.style.left = xCoord - 400 + "px"; - } else { - modalID.style.left = xCoord + 40 + "px"; - } - modalID.style.top = yCoord + "px"; - - // place dispensers - valveDiv.style.top = yCoord + "px"; - valveDiv.style.left = xCoord + "px"; - - var specificImage = template.querySelector(".dispenserImg"); - // set id of each valve anchor based on location in array - specificImage.id = i + 1; - - valveButton = template.querySelector(".valve"); - - var valveIDLabel = template.querySelector(".IDtext"); - valveIDLabel.textContent = i + 1; - if (i + 1 > 9) { - template.querySelector(".IDtext").style = "padding-left: 9px"; - } - - var catchID = "catch" + (i + 1); - gottaCatchEmAll.id = catchID; - - var dispenserTitle = template.querySelector("#dispenserModalTitle"); - dispenserTitle.textContent = "Dispenser " + (i + 1); - - // id of each syringe tube - plunger.id = "plunger" + (i + 1); - - // reference to submit appropriate form - var sendID = "dispenseTo" + (i + 1); - var vol = "dispenseVol" + (i + 1); - var time = "dispenseTime" + (i + 1); - - // form ID - form.id = "dispenseRate" + (i + 1); - sendDispense.id = sendID; - dispenseVol.id = vol; - console.log(dispenseVol.id); - dispenseTime.id = time; - console.log(dispenseTime.id); - - // dispenser orientation (push/pull) - orientation.id = "orientation" + (i + 1); - orientation.textContent = JSON.parse(localStorage.dispenserData)[i]["orientation"]; - - var dispenserCatch = "#dispenserModal" + (i + 1); - content.append(template); - // attach reference to correct dispenser modal - $("#" + catchID).attr("href", dispenserCatch); - $("#" + catchID).attr("onclick", "activateDispenser(" + (i + 1) + ")"); - } -} diff --git a/cc/legacy-neptune-control-code/ValveDispenserJSONTracking.js b/cc/legacy-neptune-control-code/ValveDispenserJSONTracking.js deleted file mode 100644 index 8689932d..00000000 --- a/cc/legacy-neptune-control-code/ValveDispenserJSONTracking.js +++ /dev/null @@ -1,146 +0,0 @@ -var ShieldIndex = 0; -var PinIndex = 0; -var deviceCount = 0; - -function initiateValveData() { - setNumberOfPumps_JSON(); -} - -// FUNCTIONALITY FOR VALVE DATA TRACKING - -// Create Valve JSON -function setNumberOfPumps_JSON() { - localStorage.pumps = JSON.parse(localStorage.portXcoords).length; - var DataToLoad = []; - var j = 0; // hardware pin (goes from 0 to 12) - for (var i = 1; i <= localStorage.pumps; i++) { - var initialize_valve_conversion = initializeSetup(180, 460, 0.69, 3, 0.88, 0.25); - var singleStage = { - id: i, - HW_shield: Math.floor(i / 12) + 1, - HW_pin: j, - Open_State: initialize_valve_conversion.uL_max, - Closed_State: 0, - Current_State: "opened", - deviceIndex: deviceCount, - uL_Conversion_Table: initialize_valve_conversion.uL_table, - uL_Precision: initialize_valve_conversion.uL_precision, - Cluster: [] - }; - DataToLoad.push(singleStage); - j = j + 1; - if (j == 13) { - j = 0; - } - ShieldIndex = i; - PinIndex = j; - deviceCount++; - } - localStorage.clear_toggle = true; - localStorage.unsavedData = JSON.stringify(DataToLoad); - localStorage.pumpData = JSON.stringify(DataToLoad); - localStorage.pumpInitial = "FALSE"; -} -function clearPumpData() { - deviceCount = 0; - var c_pumpData = []; - var j = 0; // hardware pin (goes from 0 to 12) - for (var i = 1; i <= localStorage.pumps; i++) { - var initialize_valve_conversion = initializeSetup(180, 460, 0.69, 3, 0.88, 0.25); - var singleStage = { - id: i, - HW_shield: Math.floor(i / 12) + 1, - HW_pin: j, - Open_State: initialize_valve_conversion.uL_max, - Closed_State: 0, - Current_State: "opened", - deviceIndex: deviceCount, - uL_Conversion_Table: initialize_valve_conversion.uL_table, - uL_Precision: initialize_valve_conversion.uL_precision, - Cluster: [] - }; - c_pumpData.push(singleStage); - - j = j + 1; - if (j == 13) { - j = 0; - } - deviceCount++; - } - return JSON.stringify(c_pumpData); -} -// Combine these 2 if they cannot be run non-consecutively - -// FUNCTIONALITY FOR DISPENSER DATA TRACKING AND COMMANDS -function clearDispenserData() { - var dispenserData = []; - var j = PinIndex; // hardware pin (goes from 0 to 12) - var shield = ShieldIndex; - for (var i = 1; i <= localStorage.Dispensers; i++) { - var singleStage = { - id: i, - HW_shield: Math.floor(shield / 12) + 1, - HW_pin: j, - Precision: 0, - Min: 0, - Max: 0, - Current_State: 0, - orientation: "pull", - deviceIndex: deviceCount - }; - dispenserData.push(singleStage); - j = j + 1; - if (j == 13) { - j = 0; - } - deviceCount++; - } - return JSON.stringify(dispenserData); -} - -// Create JSON for dispensers -function setNumberOfDispensers_JSON() { - localStorage.Dispensers = JSON.parse(localStorage.portXcoordsDisp).length; - var set_dispData_newNum = []; - var j = PinIndex; // hardware pin (goes from 1 to 12) - var shield = ShieldIndex; - for (var i = 1; i <= localStorage.Dispensers; i++) { - var tempDispense = { - id: i, - HW_shield: Math.floor(shield / 12) + 1, - HW_pin: j, - Precision: 0, - Min: 0, - Max: 0, - Current_State: 0, - orientation: "pull", - deviceIndex: deviceCount - }; - set_dispData_newNum.push(tempDispense); - j = j + 1; - if (j == 13) { - j = 0; - } - ShieldIndex = i; - PinIndex = j; - deviceCount++; - } - localStorage.dispenserData = JSON.stringify(set_dispData_newNum); - localStorage.dispenserInitial = "FALSE"; -} - -function clearSettingsTable() { - ShieldIndex = 0; - PinIndex = 0; - deviceCount = 0; - setNumberOfPumps_JSON(); - setNumberOfDispensers_JSON(); -} - -// THIS ENSURES SERIAL COMM LIST IS PRE-POPULATED!!! -$(document).ready(function() { - window.addEventListener("keydown", dispenseSelected); // dispenser arrow key event listener - loadButtons(); - localStorage.activeDispenser = "none"; - $.ajax({ url: "/serialcommunication/list", type: "POST", async: true, data: {}, success: function(response) {}, error: function(response) {} }); -}); diff --git a/cc/legacy-neptune-control-code/clusterValves.js b/cc/legacy-neptune-control-code/clusterValves.js deleted file mode 100644 index 868bf6ee..00000000 --- a/cc/legacy-neptune-control-code/clusterValves.js +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Created by rebeccawolf on 12/14/16. - */ - -function drawClusterTable(data) { - $("#makeValveCluster") - .find("tr:gt(0)") - .remove(); - for (var i = 0; i < data.length; i++) { - drawClusterRow(data[i]); - } -} - -function drawClusterRow(rowData) { - var row = $(""); - $("#makeValveCluster").append(row); - row.append($("" + rowData.id + "")); - var id = rowData.id.toString(); - row.append($("" + " " + "")); -} - -function updateClusterList() { - var clusterMembers = $("input[name=member]:checked") - .map(function() { - return this.value; - }) - .get(); - clusterMembers = clusterMembers.toString(); - $("#newClusterList").text("Cluster Members: " + clusterMembers); -} - -function saveCluster() { - var clusterMembers = $("input[name=member]:checked") - .map(function() { - return this.value; - }) - .get(); - - if (clusterMembers.length <= 1) { - alert("Only 1 valve selected."); - return; - } - var valves = JSON.parse(localStorage.pumpData); - - // cluster members should be numbered the same as they are in JSON format (-1) - for (var i = 0; i < clusterMembers.length; i++) { - clusterMembers[i] = clusterMembers[i] - 1; - } - - console.log(clusterMembers); - // update pumpData JSON - for (var i = 0; i < clusterMembers.length; i++) { - valves[clusterMembers[i]]["Cluster"] = clusterMembers; - console.log(valves[clusterMembers[i]]["Cluster"]); - } - - // store cluster in global cluster variable - /* - var clusterJSON = JSON.parse(localStorage.valveClusters); - clusterJSON.push({members: clusterMembers}); - */ - - localStorage.pumpData = JSON.stringify(valves); - console.log(JSON.parse(localStorage.pumpData)); -} diff --git a/cc/legacy-neptune-control-code/initiate_data.js b/cc/legacy-neptune-control-code/initiate_data.js deleted file mode 100644 index 180540d1..00000000 --- a/cc/legacy-neptune-control-code/initiate_data.js +++ /dev/null @@ -1,83 +0,0 @@ -if (localStorage.firstVisit == true || localStorage.firstVisit == undefined) { - // DECLARING PUMP VALVE STATE - - localStorage.pumpData = []; - localStorage.MasterData = []; - localStorage.unsavedData = []; - localStorage.oldPumpData = []; - localStorage.pumps = 0; - localStorage.settings_X_pos = 200; - localStorage.settings_Y_pos = 200; - - // Valve Control - localStorage.pumpData = clearPumpData(); - localStorage.valveData = initiateValveData(); - localStorage.firstVisit = false; - localStorage.pumpInitial = "TRUE"; // keeps track if this is the first time pump data is being displayed (so that its not cleared on page reload) - localStorage.valveClusters = "{}"; - - // Dispenser Control - localStorage.Dispensers = 0; - localStorage.dispenserData = clearDispenserData(); - localStorage.dispenserToControl; - localStorage.dispenserInitial == "TRUE"; // keeps track if this is the first time dispenser data is being displayed (so that its not cleared on page reload) -} -localStorage.DEBUGGER_FLAG == false; -localStorage.clear_toggle = false; -localStorage.set_pump_page_is_open = false; -localStorage.settings_toggle = "settings_is_closed"; -localStorage.close_pressed_last = false; -localStorage.hide = 0; -localStorage.settings_button_has_been_pressed_before = false; - -localStorage.SERIAL_CONSOLE_SESSION = []; - -// Variables for Valve Control (ports in Control layer) -if (localStorage.getItem("portXcoords") === null) { - localStorage.setItem("portXcoords", "default"); -} - -if (localStorage.getItem("portYcoords") === null) { - localStorage.setItem("portYcoords", "default"); -} - -if (localStorage.getItem("portRadius1vals") === null) { - localStorage.setItem("portRadius1vals", "default"); -} - -if (localStorage.getItem("portRadius2vals") === null) { - localStorage.setItem("portRadius2vals", "default"); -} - -if (localStorage.getItem("portToControl") == null) { - localStorage.setItem("portToControl", "null"); -} - -// Variables for Dispenser Control (ports in flow layer) -if (localStorage.getItem("portXcoordsDisp") === null) { - localStorage.setItem("portXcoordsDisp", "default"); -} - -if (localStorage.getItem("portYcoordsDisp") === null) { - localStorage.setItem("portYcoordsDisp", "default"); -} - -if (localStorage.getItem("DispenserToControl") == null) { - localStorage.setItem("DispenserToControl", "null"); -} -if (localStorage.getItem("activeDispenser") == null) { - localStorage.setItem("activeDispenser", "none"); -} -if (localStorage.getItem("dispenserConversions") == null) { - localStorage.setItem("dispenserConversions", "{}"); -} - -console.log("checking JSONloaded now in initiate_data.js"); -if (localStorage.getItem("JSONloaded") == undefined) { - localStorage.setItem("JSONloaded", "false"); - console.log("Successfully set JSONloaded to false in initiate_data.js"); -} - -if (localStorage.getItem("JSONtoLoad") == null) { - localStorage.setItem("JSONtoLoad", "{}"); -} diff --git a/cc/ui/canvas.js b/cc/ui/canvas.js deleted file mode 100644 index b9fc6f42..00000000 --- a/cc/ui/canvas.js +++ /dev/null @@ -1,27 +0,0 @@ -/** - * This one will host code that handles the clicks and then basically transmit the valve switching code from here - **/ - -import Setup from "../control/setup"; - -export default class Canvas { - constructor(setup) { - /* - Step 1: Retrieve the microfluidic object - Step 2: Send the valves and callback function to 3DuF - Step 3: - */ - let json = setup.Chip.JSON; - this.__setup = setup; - this.__valves = setup.Chip.getValves(); - //TODO: Call "new" 3DuF API to load the json on it. - console.log("Assuming 3DuF creates the function"); - console.log("load the microfuidic json"); - console.log("pass valves and callback"); - } - - callbackfunction(valveid) { - //This is the callback function which eventually actuates all the pumps - this.__setup.toggleValve(valveid); - } -} diff --git a/cc/ui/controlModal.js b/cc/ui/controlModal.js deleted file mode 100644 index 9d5aca3d..00000000 --- a/cc/ui/controlModal.js +++ /dev/null @@ -1,115 +0,0 @@ -/** - * This file would contain the ko viewmodels that bind the entire control modal to the actual data in the bg - * - * Ideally some of these methods would be disposed off - */ -// Sets up settings Modal -// Settings table save functionality - -function drawValveTable(data) { - $("#ValveTable") - .find("tr:gt(0)") - .remove(); - for (var i = 0; i < data.length; i++) { - drawValveRow(data[i]); - } -} - -function drawValveRow(rowData) { - var row = $(""); - $("#ValveTable").append(row); - row.append($("" + rowData.id + "")); - row.append($("" + rowData.HW_shield + "")); - row.append($("" + rowData.HW_pin + "")); - //row.append($("" + rowData.Open_State + "")); - //row.append($("" + rowData.Closed_State + "")); - row.append($("" + rowData.Open_State + "")); - row.append($("" + rowData.Closed_State + "")); - row.append($("" + rowData.Current_State + "")); -} - -// A few jQuery helpers for exporting only -jQuery.fn.pop = [].pop; -jQuery.fn.shift = [].shift; - -function exporting() { - var $rows = $("#ValveTable").find("tr:not(:hidden):not(:empty)"); - var keys = ["id", "HW_shield", "HW_pin", "Open_State", "Closed_State", "Current_State"]; - var x = 0; // making sure we are not counting the headers row here - var valveData = JSON.parse(localStorage.pumpData); - // Turn all existing rows into a loopable array - $rows.each(function() { - if (x > 0) { - var $td = $(this).find("td"); - // Use pre-defined Hash keys - keys.forEach(function(header, i) { - if (header === "Current_State") { - valveData[x - 1][header] = $td.eq(i).text(); - } else { - valveData[x - 1][header] = parseInt($td.eq(i).text()); - } - }); - } - x = x + 1; - }); - // Output the result - localStorage.pumpData = JSON.stringify(valveData); -} - -function drawDispenserTable(data) { - $("#DispenserTable") - .find("tr:gt(0)") - .remove(); - for (var i = 0; i < data.length; i++) { - drawDispRow(data[i]); - } -} - -function drawDispRow(rowData) { - var row = $(""); - $("#DispenserTable").append(row); - row.append($("" + rowData.id + "")); - row.append($("" + rowData.HW_shield + "")); - row.append($("" + rowData.HW_pin + "")); - row.append($("" + rowData.Precision + "")); - row.append($("" + rowData.Min + "")); - row.append($("" + rowData.Max + "")); - row.append($("" + rowData.Current_State + "")); - row.append($("" + rowData.orientation + "")); -} - -function exportingDispenser() { - var $rows = $("#DispenserTable").find("tr:not(:hidden):not(:empty)"); - var keys = ["id", "HW_shield", "HW_pin", "Precision", "Min", "Max", "Current_State", "orientation"]; - var x = 0; // making sure we are not counting the headers row here - var dispenserData = JSON.parse(localStorage.dispenserData); - // Turn all existing rows into a loopable array - $rows.each(function() { - if (x > 0) { - var $td = $(this).find("td"); - // Use pre-defined Hash keys - keys.forEach(function(header, i) { - if (header === "Current_State") { - dispenserData[x - 1][header] = parseFloat($td.eq(i).text()).toFixed(1); - } else if (header === "Precision") { - dispenserData[x - 1][header] = $td.eq(i).text(); - } else if (header === "Min") { - dispenserData[x - 1][header] = parseFloat($td.eq(i).text()).toFixed(1); - } else if (header === "Max") { - dispenserData[x - 1][header] = parseFloat($td.eq(i).text()).toFixed(1); - } else { - dispenserData[x - 1][header] = parseInt($td.eq(i).text()); - } - }); - } - x = x + 1; - }); - // Output the result - localStorage.dispenserData = JSON.stringify(dispenserData); -} - -function totalExport() { - deviceCount = 0; - exporting(); - exportingDispenser(); -} diff --git a/cc/ui/dispenserModal.js b/cc/ui/dispenserModal.js deleted file mode 100644 index 0cf27354..00000000 --- a/cc/ui/dispenserModal.js +++ /dev/null @@ -1,126 +0,0 @@ -/** - * This needs to be split up between the modal ui code and the dispenser hardware code - */ - -// Controls initializing dispensers if they have not been already -// triggers commands to be sent for dispensing -// functionality for changing dispenser orientation - -function sendDispense(sender) { - // VALUES FROM THE FORM: - var form = sender.parentNode.parentNode; - var volume = form.querySelector(".dispenseVol"); - var time = form.querySelector(".dispenseTime"); - var dispenserID = sender.id; // ID of dispenser you are controlling - dispenserID = dispenserID.replace(/\D/g, ""); - //console.log("Dispenser to be controlled is: " + dispenserID); - - if (isNaN(volume.value)) { - toastr.error("Please enter a valid number for dispense volume."); - return false; - } else if (isNaN(time.value)) { - toastr.error("Please enter a valid number for dispense time."); - return false; - } else { - var currentVolume = parseFloat(JSON.parse(localStorage.dispenserData)[dispenserID - 1]["Current_State"]); // current volume state of selected syringe - //var precision = parseFloat(JSON.parse(localStorage.dispenserData)[dispenserID - 1]['Precision']); // pull precision from settings table - - // Hardware computations - // Digital Servos 12cc - var initializeSetup_outputs = initializeSetup(1000, 2500, 0.625, 3, 0, 0.25); - var PWM_table = initializeSetup_outputs.PWM_table; - var PWM_dic = initializeSetup_outputs.PWM_dic; - var uL_table = initializeSetup_outputs.uL_table; - var uL_dic = initializeSetup_outputs.uL_dic; - var uL_min = initializeSetup_outputs.uL_min; - var uL_max = initializeSetup_outputs.uL_max; - var uL_precision = initializeSetup_outputs.uL_precision; - - var globalDispenserData = JSON.parse(localStorage.dispenserData); - globalDispenserData[dispenserID - 1]["Min"] = uL_min.toString(); - globalDispenserData[dispenserID - 1]["Max"] = uL_max.toString(); - globalDispenserData[dispenserID - 1]["Precision"] = uL_precision.toString(); - localStorage.dispenserData = JSON.stringify(globalDispenserData); - - console.log("conversions (PWM and uL): "); - console.log(PWM_table); - console.log(uL_table); - - //var temp = JSON.parse(localStorage.dispenserData); - globalDispenserData[dispenserID - 1]["Min"] = uL_min.toFixed(2).toString(); - globalDispenserData[dispenserID - 1]["Max"] = uL_max.toFixed(2).toString(); - globalDispenserData[dispenserID - 1]["Precision"] = uL_precision.toFixed(2).toString(); - localStorage.dispenserData = JSON.stringify(globalDispenserData); - - // DISPENSERCONVERSIONS NOT DEFINED BEFORE HERE???? - - // store conversion tables to be accessed by other parts of dispense operations - var storedConversions = JSON.parse(localStorage.dispenserConversions); // load here so as not to overwrite tables already stored - storedConversions[dispenserID] = JSON.stringify(uL_table); // update computed conversions in temp variable - localStorage.dispenserConversions = JSON.stringify(storedConversions); // store temp in localStorage - // console.log("uL table: "); - // console.log(uL_table); - - var dispOrientation = JSON.parse(localStorage.dispenserData)[dispenserID - 1]["orientation"]; // determine whether is pull/push dispenser - var valueToDispense; - - // COMPUTE VALUE TO PASS INTO even_uL_steps() - if (dispOrientation === "push") { - valueToDispense = currentVolume - parseFloat(volume.value); - if (valueToDispense < 0) { - toastr.error("Requested dispense volume exceedes remaining syringe volume"); - } - } else { - // pull orientaion - valueToDispense = currentVolume + parseFloat(volume.value); - if (valueToDispense >= parseFloat(globalDispenserData[dispenserID - 1]["Max"]) - parseFloat(globalDispenserData[dispenserID - 1]["Current_State"])) { - toastr.error("Requested dispense volume exceedes remaining syringe volume"); - } - } - - var even_uL_steps_output = even_uL_steps(uL_table, PWM_table, uL_precision, currentVolume, valueToDispense, time.value); // [0] is seconds/step [1] is PWM value array to be sent - // values needed for dispense rate - var msecondsPerStep = even_uL_steps_output.seconds_per_step * 1000; // must be in milliseconds - var stepsPerSecond = even_uL_steps_output.steps_per_second; // conversions only for commands being sent at the moment (this way its easier to update the current volume) - var PWMvalueArray = even_uL_steps_output.PWM_values; - - // set correct dispenser to command - localStorage.dispenserToControl = dispenserID; - - // iterate over command array at appropriate time intervals - for (var i = 0; i < PWMvalueArray.length; i++) { - (function() { - // need to re-define some variables here due to scope - var iPrime = i; - var dispenser_to_control = dispenserID; - setTimeout(function() { - if (PWMvalueArray[iPrime] != PWMvalueArray[iPrime - 1]) { - var temp = JSON.parse(localStorage.dispenserData); - temp[dispenserID - 1]["Current_State"] = PWM_dic[PWMvalueArray[iPrime]].toString(); - localStorage.dispenserData = JSON.stringify(temp); // update local storage to correct new volume amount - sendCommandDispense(PWMvalueArray[iPrime], dispenser_to_control); // now send command - updateDispenseProgressBar(dispenser_to_control); // and update graphics - } - }, i * msecondsPerStep); - })(); - } - return false; - } -} - -function changeDispenseOrientation(sender) { - var dispenserID = sender.id.replace(/\D/g, ""); - var temp = JSON.parse(localStorage.dispenserData); - var currentOrientation = sender.innerHTML; - if (currentOrientation === "pull") { - sender.innerHTML = "push"; - temp[dispenserID - 1]["orientation"] = "push"; - localStorage.dispenserData = JSON.stringify(temp); - } else { - // currentOrientation === "push" - sender.innerHTML = "pull"; - temp[dispenserID - 1]["orientation"] = "pull"; - localStorage.dispenserData = JSON.stringify(temp); - } - return false; -} diff --git a/cc/ui/togglebutton.js b/cc/ui/togglebutton.js deleted file mode 100644 index 7d29f738..00000000 --- a/cc/ui/togglebutton.js +++ /dev/null @@ -1,127 +0,0 @@ -// functionality attached directly to valve icons; find in JSONValveDispenserLoad.js -function onclickanchortag() { - var temp = JSON.parse(localStorage.pumpData); - var valve_to_control = this.id.split("valve").pop(); - if (temp[valve_to_control - 1]["Cluster"].length > 0) { - for (var i = 0; i < temp[valve_to_control - 1]["Cluster"].length; i++) { - toggleValve("#valve" + (temp[valve_to_control - 1]["Cluster"][i] + 1)); - } - } else { - toggleValve("#" + this.id); - } - return false; -} - -// toggle any valve given its DivID -function toggleValve(valveDivID) { - // will be in form of #valve1, #valve2, ... numbers correspond to valve id in JSON - var divElement = $(valveDivID)[0]; - var location = getLocation(divElement.src); - var valve_to_control = divElement.id.split("valve").pop(); - var temp = JSON.parse(localStorage.pumpData); - switch (location.pathname) { - case "/images/fluigi/valveMarkerOpen.svg": - $(divElement).attr("src", "../images/fluigi/valveMarkerClosed.svg"); - // change recorded state in table - temp[valve_to_control - 1]["Current_State"] = "closed"; - break; - - case "/images/fluigi/valveMarkerClosed.svg": - $(divElement).attr("src", "../images/fluigi/valveMarkerOpen.svg"); - // change recorded state in table - temp[valve_to_control - 1]["Current_State"] = "opened"; - break; - default: - $(this).attr("src", "../images/fluigi/valveMarkerClosed.svg"); - break; - } - localStorage.pumpData = JSON.stringify(temp); - localStorage.portToControl = valve_to_control; - sendCommand(); - if (location.pathname == "/images/fluigi/valveMarkerOpen.svg") { - } - return false; -} - -var getLocation = function(href) { - var l = document.createElement("a"); - l.href = href; - return l; -}; - -function onclickanchortagDispense() { - dispenser_to_control = this.id; - incrementDispenserPosition(dispenser_to_control); - return false; -} - -// functionality directly connected to dispenser icons; find in JSONValveDispenserLoad.js -function activateDispenser(dispenserIDNum) { - localStorage.activeDispenser = dispenserIDNum; - localStorage.dispenserToControl = dispenserIDNum; - updateDispenseProgressBar(dispenserIDNum); -} -function deactivateDispenser() { - localStorage.activeDispenser = "none"; -} - -function valve_uL_to_PWM(uL_table, uL_precision, uL_goal) { - for (var i = 0; i <= uL_table.length; i = i + 2) { - if (uL_goal - uL_table[i] <= uL_precision / 2) { - return Math.round(uL_table[i + 1]); - } - } - console.log("ERROR! Cannot find value"); -} - -function wrap_data_for_Arduino() { - var valve_to_control = localStorage.portToControl; - - var data_for_selected_object = JSON.parse(localStorage.pumpData); - var deviceNum = data_for_selected_object[valve_to_control - 1]["deviceIndex"]; - console.log("wrapping command for " + deviceNum); - var open_state_parameter = data_for_selected_object[valve_to_control - 1]["Open_State"]; - var closed_state_parameter = data_for_selected_object[valve_to_control - 1]["Closed_State"]; - var physical_state_parameter = data_for_selected_object[valve_to_control - 1]["Current_State"]; - - if (physical_state_parameter == "opened") { - var uLVal = open_state_parameter; - } else { - var uLVal = closed_state_parameter; - } - - var uL_table = data_for_selected_object[valve_to_control - 1]["uL_Conversion_Table"]; - //console.log("uL_table: " + uL_table); - var uL_precision = data_for_selected_object[valve_to_control - 1]["uL_Precision"]; - var PWMval = valve_uL_to_PWM(uL_table, uL_precision, uLVal); - - // PAD THE VALVE_TO_CONTROL WITH 0's SUCH THAT THE VALUE IS 4 CHARACTERS LONG - var valve_to_control_padded = zeroFill(deviceNum, 4); - // PAD THE PWM VALUE WITH 0's SUCH THAT THE VALUE IS 4 CHARACTERS LONG - var PWMval_padded = zeroFill(PWMval, 4); - // CONCAT THE VALVE NUMBER AND PWM VALUE - var pre_command = valve_to_control_padded.concat(PWMval_padded); - // ADD A START CODON TO SIGNIFY THE BEGINING OF SIGNAL - var startStr = ""; - var pre_command_s = startStr.concat(pre_command); - // ADD A STOP CODON TO SIGNIFY THE END OF SIGNAL - var command = pre_command_s.concat("\n"); - // RETURN THE DATA - return command; -} - -function sendCommand() { - var command = wrap_data_for_Arduino(); - toastr.info(command); - localStorage.setItem("myCommand", command); - $.ajax({ - url: "/serialcommunication/send", - type: "POST", - async: true, - data: { - commandData: command - }, - success: function(response) {}, - error: function(response) {} - }); -} diff --git a/conf.json b/conf.json deleted file mode 100644 index 5d0d0ef3..00000000 --- a/conf.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "source": { - "includePattern": ".+\\.js(doc|x)?$", // Only process file ending in .js, .jsdoc or .jsx - "include": ["./src/app/"], // Check all folders. - "exclude": ["node_modules"] // Be gone, node_modules. - }, - "recurseDepth": 10, // Only go 10 levels deep. - "opts": { - "destination": "./docs/", // Where I want my docs to be generated. - "recurse": true // Same as using -r or --recurse - } -} diff --git a/dist/css/app.85a0644e.css b/css/app.85a0644e.css similarity index 100% rename from dist/css/app.85a0644e.css rename to css/app.85a0644e.css diff --git a/dist/css/chunk-vendors.acfd7f9b.css b/css/chunk-vendors.acfd7f9b.css similarity index 100% rename from dist/css/chunk-vendors.acfd7f9b.css rename to css/chunk-vendors.acfd7f9b.css diff --git a/dist/demo.css b/demo.css similarity index 100% rename from dist/demo.css rename to demo.css diff --git a/doc/mint-primitives.png b/doc/mint-primitives.png deleted file mode 100644 index d150f560..00000000 Binary files a/doc/mint-primitives.png and /dev/null differ diff --git a/doc/ui.png b/doc/ui.png deleted file mode 100644 index a45a7e08..00000000 Binary files a/doc/ui.png and /dev/null differ diff --git a/examples/COSMIC_OWL.json b/examples/COSMIC_OWL.json deleted file mode 100644 index 7a9cf90e..00000000 --- a/examples/COSMIC_OWL.json +++ /dev/null @@ -1,766 +0,0 @@ -{ - "name": "My Device", - "params": { "width": 75800, "height": 51000 }, - "layers": [ - { - "name": "flow", - "color": "indigo", - "params": { "z_offset": 0, "flip": false }, - "features": { - "6bb96ad0-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb96ad0-3d80-11e5-898a-2de600a0e2af", - "name": "New Port", - "type": "Port", - "params": { "position": [30000, 40000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "6bb96ad1-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb96ad1-3d80-11e5-898a-2de600a0e2af", - "name": "New Port", - "type": "Port", - "params": { "position": [40000, 40000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "6bb96ad2-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb96ad2-3d80-11e5-898a-2de600a0e2af", - "name": "New Port", - "type": "Port", - "params": { "position": [50000, 40000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "6bb96ad3-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb96ad3-3d80-11e5-898a-2de600a0e2af", - "name": "New Port", - "type": "Port", - "params": { "position": [20000, 40000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "6bb991e0-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb991e0-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [20000, 40000], "end": [20000, 35000], "width": 400, "height": 100 } - }, - "6bb991e1-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb991e1-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [20000, 38000], "end": [17000, 38000], "width": 400, "height": 100 } - }, - "6bb991e2-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb991e2-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [17000, 38000], "end": [17000, 35000], "width": 400, "height": 100 } - }, - "6bb991e3-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb991e3-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [20000, 35000], "end": [20000, 20000], "width": 400, "height": 100 } - }, - "6bb991e4-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb991e4-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [20000, 20000], "end": [10000, 10000], "width": 400, "height": 100 } - }, - "6bb991e5-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb991e5-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [17000, 35000], "end": [15000, 30000], "width": 400, "height": 100 } - }, - "6bb991e6-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb991e6-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [15000, 30000], "end": [10000, 30000], "width": 400, "height": 100 } - }, - "6bb991e7-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb991e7-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [10000, 30000], "end": [10000, 28000], "width": 400, "height": 100 } - }, - "6bb991e8-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb991e8-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [10000, 28000], "end": [15000, 28000], "width": 400, "height": 100 } - }, - "6bb991e9-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb991e9-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [15000, 28000], "end": [15000, 25000], "width": 400, "height": 100 } - }, - "6bb991ea-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb991ea-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [15000, 25000], "end": [8000, 25000], "width": 400, "height": 100 } - }, - "6bb991eb-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb991eb-3d80-11e5-898a-2de600a0e2af", - "name": "New Port", - "type": "Port", - "params": { "position": [8000, 25000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "6bb991ec-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb991ec-3d80-11e5-898a-2de600a0e2af", - "name": "New Port", - "type": "Port", - "params": { "position": [10000, 10000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "6bb991ed-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb991ed-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [30000, 40000], "end": [30000, 20000], "width": 400, "height": 100 } - }, - "6bb991ee-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb991ee-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [30000, 20000], "end": [20000, 10000], "width": 400, "height": 100 } - }, - "6bb991ef-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb991ef-3d80-11e5-898a-2de600a0e2af", - "name": "New Port", - "type": "Port", - "params": { "position": [20000, 10000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "6bb991f0-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb991f0-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [30000, 38000], "end": [27000, 38000], "width": 400, "height": 100 } - }, - "6bb991f1-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb991f1-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [27000, 38000], "end": [27000, 30000], "width": 400, "height": 100 } - }, - "6bb991f2-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb991f2-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [27000, 30000], "end": [22000, 30000], "width": 400, "height": 100 } - }, - "6bb991f3-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb991f3-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [22000, 30000], "end": [22000, 28000], "width": 400, "height": 100 } - }, - "6bb991f4-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb991f4-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [22000, 28000], "end": [27000, 28000], "width": 400, "height": 100 } - }, - "6bb991f5-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb991f5-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [27000, 28000], "end": [27000, 26000], "width": 400, "height": 100 } - }, - "6bb991f6-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb991f6-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [27000, 26000], "end": [22000, 26000], "width": 400, "height": 100 } - }, - "6bb991f7-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb991f7-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [22000, 26000], "end": [22000, 24000], "width": 400, "height": 100 } - }, - "6bb991f8-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb991f8-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [22000, 24000], "end": [27000, 24000], "width": 400, "height": 100 } - }, - "6bb991f9-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb991f9-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [27000, 24000], "end": [27000, 22000], "width": 400, "height": 100 } - }, - "6bb991fa-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb991fa-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [27000, 22000], "end": [22000, 22000], "width": 400, "height": 100 } - }, - "6bb991fb-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb991fb-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [22000, 22000], "end": [22000, 20000], "width": 400, "height": 100 } - }, - "6bb991fc-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb991fc-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [22000, 20000], "end": [25000, 20000], "width": 400, "height": 100 } - }, - "6bb991fd-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb991fd-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [25000, 20000], "end": [25000, 17000], "width": 400, "height": 100 } - }, - "6bb991fe-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb991fe-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [25000, 17000], "end": [21000, 17000], "width": 400, "height": 100 } - }, - "6bb9b8f0-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9b8f0-3d80-11e5-898a-2de600a0e2af", - "name": "New Port", - "type": "Port", - "params": { "position": [21000, 17000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "6bb9b8f1-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9b8f1-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [40000, 40000], "end": [40000, 20000], "width": 400, "height": 100 } - }, - "6bb9b8f2-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9b8f2-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [40000, 20000], "end": [50000, 10000], "width": 400, "height": 100 } - }, - "6bb9b8f3-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9b8f3-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [40000, 38000], "end": [43000, 38000], "width": 400, "height": 100 } - }, - "6bb9b8f4-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9b8f4-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [43000, 38000], "end": [43000, 30000], "width": 400, "height": 100 } - }, - "6bb9b8f5-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9b8f5-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [43000, 30000], "end": [48000, 30000], "width": 400, "height": 100 } - }, - "6bb9b8f6-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9b8f6-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [48000, 30000], "end": [48000, 28000], "width": 400, "height": 100 } - }, - "6bb9b8f7-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9b8f7-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [48000, 28000], "end": [43000, 28000], "width": 400, "height": 100 } - }, - "6bb9b8f8-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9b8f8-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [43000, 28000], "end": [43000, 26000], "width": 400, "height": 100 } - }, - "6bb9b8f9-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9b8f9-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [43000, 26000], "end": [48000, 26000], "width": 400, "height": 100 } - }, - "6bb9b8fa-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9b8fa-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [48000, 26000], "end": [48000, 24000], "width": 400, "height": 100 } - }, - "6bb9b8fb-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9b8fb-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [48000, 24000], "end": [43000, 24000], "width": 400, "height": 100 } - }, - "6bb9b8fc-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9b8fc-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [43000, 24000], "end": [43000, 22000], "width": 400, "height": 100 } - }, - "6bb9b8fd-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9b8fd-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [43000, 22000], "end": [48000, 22000], "width": 400, "height": 100 } - }, - "6bb9b8fe-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9b8fe-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [48000, 22000], "end": [48000, 20000], "width": 400, "height": 100 } - }, - "6bb9b8ff-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9b8ff-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [48000, 20000], "end": [45000, 20000], "width": 400, "height": 100 } - }, - "6bb9b900-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9b900-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [45000, 20000], "end": [45000, 17000], "width": 400, "height": 100 } - }, - "6bb9b901-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9b901-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [45000, 17000], "end": [49000, 17000], "width": 400, "height": 100 } - }, - "6bb9b902-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9b902-3d80-11e5-898a-2de600a0e2af", - "name": "New Port", - "type": "Port", - "params": { "position": [50000, 10000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "6bb9b903-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9b903-3d80-11e5-898a-2de600a0e2af", - "name": "New Port", - "type": "Port", - "params": { "position": [49000, 17000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "6bb9b904-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9b904-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [50000, 40000], "end": [50000, 20000], "width": 400, "height": 100 } - }, - "6bb9b905-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9b905-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [50000, 20000], "end": [60000, 10000], "width": 400, "height": 100 } - }, - "6bb9b906-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9b906-3d80-11e5-898a-2de600a0e2af", - "name": "New Port", - "type": "Port", - "params": { "position": [60000, 10000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "6bb9e000-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9e000-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [50000, 38000], "end": [53000, 38000], "width": 400, "height": 100 } - }, - "6bb9e001-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9e001-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [53000, 38000], "end": [53000, 35000], "width": 400, "height": 100 } - }, - "6bb9e002-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9e002-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [53000, 35000], "end": [55000, 30000], "width": 400, "height": 100 } - }, - "6bb9e003-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9e003-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [55000, 30000], "end": [60000, 30000], "width": 400, "height": 100 } - }, - "6bb9e004-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9e004-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [60000, 30000], "end": [60000, 28000], "width": 400, "height": 100 } - }, - "6bb9e005-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9e005-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [60000, 28000], "end": [55000, 28000], "width": 400, "height": 100 } - }, - "6bb9e006-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9e006-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [55000, 28000], "end": [55000, 25000], "width": 400, "height": 100 } - }, - "6bb9e007-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9e007-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [55000, 25000], "end": [62000, 25000], "width": 400, "height": 100 } - }, - "6bb9e008-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9e008-3d80-11e5-898a-2de600a0e2af", - "name": "New Port", - "type": "Port", - "params": { "position": [62000, 25000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "6bb9e009-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9e009-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [15000, 15000], "end": [15000, 12000], "width": 400, "height": 100 } - }, - "6bb9e00a-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9e00a-3d80-11e5-898a-2de600a0e2af", - "name": "New Via", - "type": "Via", - "params": { "position": [15000, 12000], "radius1": 800, "radius2": 700, "height": 1000 } - }, - "6bb9e00b-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9e00b-3d80-11e5-898a-2de600a0e2af", - "name": "New Via", - "type": "Via", - "params": { "position": [26000, 12000], "radius1": 800, "radius2": 700, "height": 1000 } - }, - "6bb9e00c-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9e00c-3d80-11e5-898a-2de600a0e2af", - "name": "New Via", - "type": "Via", - "params": { "position": [44000, 12000], "radius1": 800, "radius2": 700, "height": 1000 } - }, - "6bb9e00d-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9e00d-3d80-11e5-898a-2de600a0e2af", - "name": "New Via", - "type": "Via", - "params": { "position": [55000, 12000], "radius1": 800, "radius2": 700, "height": 1000 } - }, - "6bb9e00e-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9e00e-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [55000, 12000], "end": [55000, 15000], "width": 400, "height": 100 } - }, - "6bb9e00f-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9e00f-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [26000, 12000], "end": [30000, 10000], "width": 400, "height": 100 } - }, - "6bb9e010-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9e010-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [44000, 12000], "end": [40000, 10000], "width": 400, "height": 100 } - }, - "6bb9e011-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9e011-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [40000, 10000], "end": [38000, 7000], "width": 400, "height": 100 } - }, - "6bb9e012-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9e012-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [30000, 10000], "end": [32000, 7000], "width": 400, "height": 100 } - }, - "6bb9e013-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9e013-3d80-11e5-898a-2de600a0e2af", - "name": "New Port", - "type": "Port", - "params": { "position": [32000, 7000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "6bb9e014-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9e014-3d80-11e5-898a-2de600a0e2af", - "name": "New Port", - "type": "Port", - "params": { "position": [38000, 7000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "6bb9e015-3d80-11e5-898a-2de600a0e2af": { - "id": "6bb9e015-3d80-11e5-898a-2de600a0e2af", - "name": "New CircleValve", - "type": "CircleValve", - "params": { "position": [35000, 10000], "radius1": 1400, "radius2": 1200, "height": 800 } - }, - "6bba0710-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba0710-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [35000, 10000], "end": [35000, 30000], "width": 400, "height": 100 } - }, - "6bba0711-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba0711-3d80-11e5-898a-2de600a0e2af", - "name": "New Port", - "type": "Port", - "params": { "position": [35000, 30000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "6bba0712-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba0712-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [35000, 17000], "end": [38000, 23000], "width": 400, "height": 100 } - }, - "6bba0713-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba0713-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [38000, 23000], "end": [36000, 25000], "width": 400, "height": 100 } - }, - "6bba0714-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba0714-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [36000, 25000], "end": [35000, 30000], "width": 400, "height": 100 } - }, - "6bba0715-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba0715-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [35000, 17000], "end": [32000, 23000], "width": 400, "height": 100 } - }, - "6bba0716-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba0716-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [32000, 23000], "end": [34000, 25000], "width": 400, "height": 100 } - }, - "6bba0717-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba0717-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [34000, 25000], "end": [35000, 30000], "width": 400, "height": 100 } - }, - "6bba0718-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba0718-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [32000, 23000], "end": [35000, 24000], "width": 400, "height": 100 } - }, - "6bba0719-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba0719-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [38000, 23000], "end": [35000, 24000], "width": 400, "height": 100 } - }, - "6bba071a-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba071a-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [25000, 20000], "end": [28000, 20000], "width": 400, "height": 100 } - }, - "6bba071b-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba071b-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [28000, 20000], "end": [28000, 22000], "width": 400, "height": 100 } - }, - "6bba071c-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba071c-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [28000, 22000], "end": [27000, 22000], "width": 400, "height": 100 } - }, - "6bba071d-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba071d-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [45000, 20000], "end": [42000, 20000], "width": 400, "height": 100 } - }, - "6bba071e-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba071e-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [42000, 20000], "end": [42000, 22000], "width": 400, "height": 100 } - }, - "6bba071f-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba071f-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [42000, 22000], "end": [44000, 22000], "width": 400, "height": 100 } - }, - "8d30ec10-3d80-11e5-898a-2de600a0e2af": { - "id": "8d30ec10-3d80-11e5-898a-2de600a0e2af", - "name": "New Via", - "type": "Via", - "params": { "position": [35000, 30000], "radius1": 800, "radius2": 700, "height": 1000 } - }, - "9b26fd00-3d80-11e5-898a-2de600a0e2af": { - "id": "9b26fd00-3d80-11e5-898a-2de600a0e2af", - "name": "New Via", - "type": "Via", - "params": { "position": [32000, 20000], "radius1": 800, "radius2": 700, "height": 1000 } - }, - "9c3deb40-3d80-11e5-898a-2de600a0e2af": { - "id": "9c3deb40-3d80-11e5-898a-2de600a0e2af", - "name": "New Via", - "type": "Via", - "params": { "position": [38000, 20000], "radius1": 800, "radius2": 700, "height": 1000 } - } - } - }, - { - "name": "control", - "color": "red", - "params": { "z_offset": 1200, "flip": true }, - "features": { - "6bba0720-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba0720-3d80-11e5-898a-2de600a0e2af", - "name": "New CircleValve", - "type": "CircleValve", - "params": { "position": [20000, 34000], "radius1": 1400, "radius2": 1200, "height": 800 } - }, - "6bba0721-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba0721-3d80-11e5-898a-2de600a0e2af", - "name": "New CircleValve", - "type": "CircleValve", - "params": { "position": [30000, 34000], "radius1": 1400, "radius2": 1200, "height": 800 } - }, - "6bba0722-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba0722-3d80-11e5-898a-2de600a0e2af", - "name": "New CircleValve", - "type": "CircleValve", - "params": { "position": [40000, 34000], "radius1": 1400, "radius2": 1200, "height": 800 } - }, - "6bba0723-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba0723-3d80-11e5-898a-2de600a0e2af", - "name": "New CircleValve", - "type": "CircleValve", - "params": { "position": [50000, 34000], "radius1": 1400, "radius2": 1200, "height": 800 } - }, - "6bba0724-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba0724-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [20000, 34000], "end": [24000, 34000], "width": 400, "height": 100 } - }, - "6bba0725-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba0725-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [24000, 34000], "end": [24000, 47000], "width": 400, "height": 100 } - }, - "6bba0726-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba0726-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [30000, 34000], "end": [34000, 34000], "width": 400, "height": 100 } - }, - "6bba0727-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba0727-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [34000, 34000], "end": [34000, 47000], "width": 400, "height": 100 } - }, - "6bba0728-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba0728-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [40000, 34000], "end": [37000, 34000], "width": 400, "height": 100 } - }, - "6bba0729-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba0729-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [37000, 34000], "end": [36000, 34000], "width": 400, "height": 100 } - }, - "6bba072a-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba072a-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [36000, 34000], "end": [36000, 47000], "width": 400, "height": 100 } - }, - "6bba072b-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba072b-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [50000, 34000], "end": [46000, 34000], "width": 400, "height": 100 } - }, - "6bba072c-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba072c-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [46000, 34000], "end": [46000, 47000], "width": 400, "height": 100 } - }, - "6bba072d-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba072d-3d80-11e5-898a-2de600a0e2af", - "name": "New Port", - "type": "Port", - "params": { "position": [24000, 47000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "6bba072e-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba072e-3d80-11e5-898a-2de600a0e2af", - "name": "New Port", - "type": "Port", - "params": { "position": [34000, 47000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "6bba072f-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba072f-3d80-11e5-898a-2de600a0e2af", - "name": "New Port", - "type": "Port", - "params": { "position": [36000, 47000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "6bba0730-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba0730-3d80-11e5-898a-2de600a0e2af", - "name": "New Port", - "type": "Port", - "params": { "position": [46000, 47000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "6bba2e20-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba2e20-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [15000, 12000], "end": [26000, 12000], "width": 400, "height": 100 } - }, - "6bba2e21-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba2e21-3d80-11e5-898a-2de600a0e2af", - "name": "New Channel", - "type": "Channel", - "params": { "start": [44000, 12000], "end": [55000, 12000], "width": 400, "height": 100 } - }, - "6bba2e22-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba2e22-3d80-11e5-898a-2de600a0e2af", - "name": "New Port", - "type": "Port", - "params": { "position": [15000, 12000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "6bba2e23-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba2e23-3d80-11e5-898a-2de600a0e2af", - "name": "New Port", - "type": "Port", - "params": { "position": [26000, 12000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "6bba2e24-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba2e24-3d80-11e5-898a-2de600a0e2af", - "name": "New Port", - "type": "Port", - "params": { "position": [44000, 12000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "6bba2e25-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba2e25-3d80-11e5-898a-2de600a0e2af", - "name": "New Port", - "type": "Port", - "params": { "position": [55000, 12000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "6bba2e26-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba2e26-3d80-11e5-898a-2de600a0e2af", - "name": "New Port", - "type": "Port", - "params": { "position": [25000, 21000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "6bba2e27-3d80-11e5-898a-2de600a0e2af": { - "id": "6bba2e27-3d80-11e5-898a-2de600a0e2af", - "name": "New Port", - "type": "Port", - "params": { "position": [45000, 21000], "radius1": 700, "radius2": 700, "height": 100 } - } - } - } - ], - "groups": [], - "defaults": {} -} diff --git a/examples/CT1211CoverBiochip_design.json b/examples/CT1211CoverBiochip_design.json deleted file mode 100644 index 1e949545..00000000 --- a/examples/CT1211CoverBiochip_design.json +++ /dev/null @@ -1,2068 +0,0 @@ -{ - "name": "My Device", - "params": { "width": 75800, "height": 51000 }, - "layers": [ - { - "name": "flow", - "color": "indigo", - "params": { "z_offset": 0, "flip": false }, - "features": { - "0b17cd40-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17cd40-3eff-11e5-93b5-5f17d678819e", - "name": "New Port", - "type": "Port", - "params": { "position": [10000, 40000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "0b17cd41-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17cd41-3eff-11e5-93b5-5f17d678819e", - "name": "New Port", - "type": "Port", - "params": { "position": [10000, 30000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "0b17f450-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f450-3eff-11e5-93b5-5f17d678819e", - "name": "New Port", - "type": "Port", - "params": { "position": [10000, 20000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "0b17f451-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f451-3eff-11e5-93b5-5f17d678819e", - "name": "New Port", - "type": "Port", - "params": { "position": [10000, 10000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "0b17f452-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f452-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [40000, 9000], "end": [40000, 2000], "width": 400, "height": 100 } - }, - "0b17f453-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f453-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [40000, 2000], "end": [39000, 2000], "width": 400, "height": 100 } - }, - "0b17f454-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f454-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [39000, 2000], "end": [39000, 8000], "width": 400, "height": 100 } - }, - "0b17f455-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f455-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [39000, 8000], "end": [38000, 8000], "width": 400, "height": 100 } - }, - "0b17f456-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f456-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [38000, 8000], "end": [38000, 2000], "width": 400, "height": 100 } - }, - "0b17f457-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f457-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [38000, 2000], "end": [37000, 2000], "width": 400, "height": 100 } - }, - "0b17f458-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f458-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [37000, 2000], "end": [37000, 8000], "width": 400, "height": 100 } - }, - "0b17f459-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f459-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [37000, 8000], "end": [36000, 8000], "width": 400, "height": 100 } - }, - "0b17f45a-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f45a-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [36000, 8000], "end": [36000, 2000], "width": 400, "height": 100 } - }, - "0b17f45b-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f45b-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [36000, 2000], "end": [35000, 2000], "width": 400, "height": 100 } - }, - "0b17f45c-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f45c-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [35000, 2000], "end": [35000, 7000], "width": 400, "height": 100 } - }, - "0b17f45d-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f45d-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [35000, 7000], "end": [34000, 7000], "width": 400, "height": 100 } - }, - "0b17f45e-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f45e-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [34000, 7000], "end": [34000, 2000], "width": 400, "height": 100 } - }, - "0b17f45f-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f45f-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [34000, 2000], "end": [33000, 2000], "width": 400, "height": 100 } - }, - "0b17f460-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f460-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [33000, 2000], "end": [33000, 7000], "width": 400, "height": 100 } - }, - "0b17f461-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f461-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [33000, 7000], "end": [32000, 7000], "width": 400, "height": 100 } - }, - "0b17f462-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f462-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [32000, 7000], "end": [32000, 2000], "width": 400, "height": 100 } - }, - "0b17f463-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f463-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [32000, 2000], "end": [30000, 2000], "width": 400, "height": 100 } - }, - "0b17f464-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f464-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [31000, 15000], "end": [32000, 15000], "width": 400, "height": 100 } - }, - "0b17f465-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f465-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [32000, 15000], "end": [32000, 21000], "width": 400, "height": 100 } - }, - "0b17f466-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f466-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [32000, 21000], "end": [33000, 21000], "width": 400, "height": 100 } - }, - "0b17f467-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f467-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [33000, 21000], "end": [33000, 15000], "width": 400, "height": 100 } - }, - "0b17f468-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f468-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [33000, 15000], "end": [34000, 15000], "width": 400, "height": 100 } - }, - "0b17f469-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f469-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [34000, 15000], "end": [34000, 21000], "width": 400, "height": 100 } - }, - "0b17f46a-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f46a-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [34000, 21000], "end": [35000, 21000], "width": 400, "height": 100 } - }, - "0b17f46b-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f46b-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [35000, 21000], "end": [35000, 15000], "width": 400, "height": 100 } - }, - "0b17f46c-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f46c-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [35000, 15000], "end": [36000, 15000], "width": 400, "height": 100 } - }, - "0b17f46d-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f46d-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [36000, 15000], "end": [36000, 22000], "width": 400, "height": 100 } - }, - "0b17f46e-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f46e-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [36000, 22000], "end": [37000, 22000], "width": 400, "height": 100 } - }, - "0b17f46f-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f46f-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [37000, 22000], "end": [37000, 15000], "width": 400, "height": 100 } - }, - "0b17f470-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f470-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [37000, 15000], "end": [38000, 15000], "width": 400, "height": 100 } - }, - "0b17f471-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f471-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [40000, 9000], "end": [40000, 19000], "width": 400, "height": 100 } - }, - "0b17f472-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f472-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [40000, 19000], "end": [41000, 20000], "width": 400, "height": 100 } - }, - "0b17f473-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f473-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [41000, 20000], "end": [60000, 20000], "width": 400, "height": 100 } - }, - "0b17f474-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f474-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [60000, 20000], "end": [60000, 17000], "width": 400, "height": 100 } - }, - "0b17f475-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f475-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [50000, 20000], "end": [49000, 21000], "width": 400, "height": 100 } - }, - "0b17f476-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f476-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [49000, 21000], "end": [41000, 21000], "width": 400, "height": 100 } - }, - "0b17f477-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f477-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [41000, 21000], "end": [39000, 19000], "width": 400, "height": 100 } - }, - "0b17f478-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f478-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [39000, 19000], "end": [39000, 14000], "width": 400, "height": 100 } - }, - "0b17f479-3eff-11e5-93b5-5f17d678819e": { - "id": "0b17f479-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [39000, 14000], "end": [32000, 12000], "width": 400, "height": 100 } - }, - "0b181b60-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b60-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [32000, 12000], "end": [26000, 12000], "width": 400, "height": 100 } - }, - "0b181b61-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b61-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [26000, 12000], "end": [20000, 2000], "width": 400, "height": 100 } - }, - "0b181b62-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b62-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [20000, 2000], "end": [16000, 2000], "width": 400, "height": 100 } - }, - "0b181b63-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b63-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [60000, 17000], "end": [55000, 12000], "width": 400, "height": 100 } - }, - "0b181b64-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b64-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [55000, 12000], "end": [53000, 10000], "width": 400, "height": 100 } - }, - "0b181b65-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b65-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [53000, 10000], "end": [53000, 5000], "width": 400, "height": 100 } - }, - "0b181b66-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b66-3eff-11e5-93b5-5f17d678819e", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [60000, 5000], "end": [62000, 7000], "borderWidth": 400, "height": 100 } - }, - "0b181b67-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b67-3eff-11e5-93b5-5f17d678819e", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [29000, 29000], "end": [31000, 31000], "borderWidth": 400, "height": 100 } - }, - "0b181b68-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b68-3eff-11e5-93b5-5f17d678819e", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [29000, 19000], "end": [31000, 21000], "borderWidth": 400, "height": 100 } - }, - "0b181b69-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b69-3eff-11e5-93b5-5f17d678819e", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [60000, 39000], "end": [62000, 41000], "borderWidth": 400, "height": 100 } - }, - "0b181b6a-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b6a-3eff-11e5-93b5-5f17d678819e", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [31000, 21000], "end": [28000, 18000], "borderWidth": 400, "height": 100 } - }, - "0b181b6b-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b6b-3eff-11e5-93b5-5f17d678819e", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [31000, 31000], "end": [28000, 28000], "borderWidth": 400, "height": 100 } - }, - "0b181b6c-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b6c-3eff-11e5-93b5-5f17d678819e", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [31000, 41000], "end": [28000, 38000], "borderWidth": 400, "height": 100 } - }, - "0b181b6d-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b6d-3eff-11e5-93b5-5f17d678819e", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [60000, 7000], "end": [63000, 4000], "borderWidth": 400, "height": 100 } - }, - "0b181b6e-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b6e-3eff-11e5-93b5-5f17d678819e", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [60000, 41000], "end": [63000, 38000], "borderWidth": 400, "height": 100 } - }, - "0b181b6f-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b6f-3eff-11e5-93b5-5f17d678819e", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [11000, 11000], "end": [8000, 8000], "borderWidth": 400, "height": 100 } - }, - "0b181b70-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b70-3eff-11e5-93b5-5f17d678819e", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [11000, 21000], "end": [8000, 18000], "borderWidth": 400, "height": 100 } - }, - "0b181b71-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b71-3eff-11e5-93b5-5f17d678819e", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [11000, 31000], "end": [8000, 28000], "borderWidth": 400, "height": 100 } - }, - "0b181b72-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b72-3eff-11e5-93b5-5f17d678819e", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [11000, 41000], "end": [8000, 38000], "borderWidth": 400, "height": 100 } - }, - "0b181b73-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b73-3eff-11e5-93b5-5f17d678819e", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [31000, 11000], "end": [28000, 8000], "borderWidth": 400, "height": 100 } - }, - "0b181b74-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b74-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [30000, 2000], "end": [30000, 8000], "width": 400, "height": 100 } - }, - "0b181b75-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b75-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [31000, 15000], "end": [30000, 15000], "width": 400, "height": 100 } - }, - "0b181b76-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b76-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [30000, 15000], "end": [30000, 19000], "width": 400, "height": 100 } - }, - "0b181b77-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b77-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [16000, 2000], "end": [10000, 9000], "width": 400, "height": 100 } - }, - "0b181b78-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b78-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [10000, 10000], "end": [9000, 10000], "width": 400, "height": 100 } - }, - "0b181b79-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b79-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [11000, 8000], "end": [2000, 18000], "width": 400, "height": 100 } - }, - "0b181b7a-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b7a-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [2000, 18000], "end": [2000, 25000], "width": 400, "height": 100 } - }, - "0b181b7b-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b7b-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [2000, 25000], "end": [30000, 25000], "width": 400, "height": 100 } - }, - "0b181b7c-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b7c-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [10000, 19000], "end": [10000, 15000], "width": 400, "height": 100 } - }, - "0b181b7d-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b7d-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [10000, 15000], "end": [10000, 14000], "width": 400, "height": 100 } - }, - "0b181b7e-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b7e-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [10000, 14000], "end": [12000, 14000], "width": 400, "height": 100 } - }, - "0b181b7f-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b7f-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [12000, 14000], "end": [12000, 18000], "width": 400, "height": 100 } - }, - "0b181b80-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b80-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [12000, 18000], "end": [13000, 18000], "width": 400, "height": 100 } - }, - "0b181b81-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b81-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [13000, 18000], "end": [13000, 14000], "width": 400, "height": 100 } - }, - "0b181b82-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b82-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [13000, 14000], "end": [14000, 14000], "width": 400, "height": 100 } - }, - "0b181b83-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b83-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [14000, 14000], "end": [14000, 18000], "width": 400, "height": 100 } - }, - "0b181b84-3eff-11e5-93b5-5f17d678819e": { - "id": "0b181b84-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [14000, 18000], "end": [14000, 19000], "width": 400, "height": 100 } - }, - "0b184270-3eff-11e5-93b5-5f17d678819e": { - "id": "0b184270-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [14000, 19000], "end": [15000, 19000], "width": 400, "height": 100 } - }, - "0b184271-3eff-11e5-93b5-5f17d678819e": { - "id": "0b184271-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [15000, 19000], "end": [15000, 14000], "width": 400, "height": 100 } - }, - "0b184272-3eff-11e5-93b5-5f17d678819e": { - "id": "0b184272-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [15000, 14000], "end": [16000, 14000], "width": 400, "height": 100 } - }, - "0b184273-3eff-11e5-93b5-5f17d678819e": { - "id": "0b184273-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [16000, 14000], "end": [16000, 22000], "width": 400, "height": 100 } - }, - "0b184274-3eff-11e5-93b5-5f17d678819e": { - "id": "0b184274-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [16000, 22000], "end": [17000, 22000], "width": 400, "height": 100 } - }, - "0b184275-3eff-11e5-93b5-5f17d678819e": { - "id": "0b184275-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [17000, 22000], "end": [17000, 14000], "width": 400, "height": 100 } - }, - "0b184276-3eff-11e5-93b5-5f17d678819e": { - "id": "0b184276-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [17000, 14000], "end": [18000, 14000], "width": 400, "height": 100 } - }, - "0b184277-3eff-11e5-93b5-5f17d678819e": { - "id": "0b184277-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [18000, 14000], "end": [18000, 22000], "width": 400, "height": 100 } - }, - "0b184278-3eff-11e5-93b5-5f17d678819e": { - "id": "0b184278-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [18000, 22000], "end": [18000, 22000], "width": 400, "height": 100 } - }, - "0b184279-3eff-11e5-93b5-5f17d678819e": { - "id": "0b184279-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [18000, 22000], "end": [19000, 22000], "width": 400, "height": 100 } - }, - "0b18427a-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18427a-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [19000, 22000], "end": [19000, 16000], "width": 400, "height": 100 } - }, - "0b18427b-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18427b-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [19000, 16000], "end": [20000, 16000], "width": 400, "height": 100 } - }, - "0b18427c-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18427c-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [20000, 16000], "end": [20000, 24000], "width": 400, "height": 100 } - }, - "0b18427d-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18427d-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [20000, 24000], "end": [30000, 24000], "width": 400, "height": 100 } - }, - "0b18427e-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18427e-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [30000, 23000], "end": [22000, 23000], "width": 400, "height": 100 } - }, - "0b18427f-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18427f-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [22000, 23000], "end": [21000, 21000], "width": 400, "height": 100 } - }, - "0b184280-3eff-11e5-93b5-5f17d678819e": { - "id": "0b184280-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [21000, 21000], "end": [21000, 15000], "width": 400, "height": 100 } - }, - "0b184281-3eff-11e5-93b5-5f17d678819e": { - "id": "0b184281-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [21000, 15000], "end": [26000, 15000], "width": 400, "height": 100 } - }, - "0b184282-3eff-11e5-93b5-5f17d678819e": { - "id": "0b184282-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [26000, 15000], "end": [26000, 14000], "width": 400, "height": 100 } - }, - "0b184283-3eff-11e5-93b5-5f17d678819e": { - "id": "0b184283-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [26000, 14000], "end": [21000, 14000], "width": 400, "height": 100 } - }, - "0b184284-3eff-11e5-93b5-5f17d678819e": { - "id": "0b184284-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [21000, 14000], "end": [21000, 13000], "width": 400, "height": 100 } - }, - "0b184285-3eff-11e5-93b5-5f17d678819e": { - "id": "0b184285-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [21000, 13000], "end": [10000, 9000], "width": 400, "height": 100 } - }, - "0b184286-3eff-11e5-93b5-5f17d678819e": { - "id": "0b184286-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [50000, 22000], "end": [49000, 23000], "width": 400, "height": 100 } - }, - "0b184287-3eff-11e5-93b5-5f17d678819e": { - "id": "0b184287-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [50000, 22000], "end": [61000, 22000], "width": 400, "height": 100 } - }, - "0b184288-3eff-11e5-93b5-5f17d678819e": { - "id": "0b184288-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [61000, 22000], "end": [61000, 17000], "width": 400, "height": 100 } - }, - "0b184289-3eff-11e5-93b5-5f17d678819e": { - "id": "0b184289-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [61000, 17000], "end": [54000, 10000], "width": 400, "height": 100 } - }, - "0b18428a-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18428a-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [49000, 23000], "end": [44000, 23000], "width": 400, "height": 100 } - }, - "0b18428b-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18428b-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [50000, 22000], "end": [44000, 22000], "width": 400, "height": 100 } - }, - "0b18428c-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18428c-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [62000, 17000], "end": [62000, 23000], "width": 400, "height": 100 } - }, - "0b18428d-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18428d-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [62000, 23000], "end": [62000, 24000], "width": 400, "height": 100 } - }, - "0b18428e-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18428e-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [62000, 24000], "end": [50000, 24000], "width": 400, "height": 100 } - }, - "0b18428f-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18428f-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [50000, 24000], "end": [49000, 25000], "width": 400, "height": 100 } - }, - "0b184290-3eff-11e5-93b5-5f17d678819e": { - "id": "0b184290-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [50000, 24000], "end": [44000, 24000], "width": 400, "height": 100 } - }, - "0b184291-3eff-11e5-93b5-5f17d678819e": { - "id": "0b184291-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [49000, 25000], "end": [44000, 25000], "width": 400, "height": 100 } - }, - "0b184292-3eff-11e5-93b5-5f17d678819e": { - "id": "0b184292-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [63000, 17000], "end": [63000, 26000], "width": 400, "height": 100 } - }, - "0b184293-3eff-11e5-93b5-5f17d678819e": { - "id": "0b184293-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [63000, 26000], "end": [50000, 26000], "width": 400, "height": 100 } - }, - "0b184294-3eff-11e5-93b5-5f17d678819e": { - "id": "0b184294-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [64000, 17000], "end": [64000, 28000], "width": 400, "height": 100 } - }, - "0b184295-3eff-11e5-93b5-5f17d678819e": { - "id": "0b184295-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [64000, 28000], "end": [50000, 28000], "width": 400, "height": 100 } - }, - "0b184296-3eff-11e5-93b5-5f17d678819e": { - "id": "0b184296-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [65000, 17000], "end": [65000, 30000], "width": 400, "height": 100 } - }, - "0b184297-3eff-11e5-93b5-5f17d678819e": { - "id": "0b184297-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [65000, 17000], "end": [66000, 10000], "width": 400, "height": 100 } - }, - "0b184298-3eff-11e5-93b5-5f17d678819e": { - "id": "0b184298-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [59000, 3000], "end": [59000, 1000], "width": 400, "height": 100 } - }, - "0b184299-3eff-11e5-93b5-5f17d678819e": { - "id": "0b184299-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [59000, 1000], "end": [74000, 1000], "width": 400, "height": 100 } - }, - "0b18429a-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18429a-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [74000, 1000], "end": [74000, 40000], "width": 400, "height": 100 } - }, - "0b18429b-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18429b-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [74000, 40000], "end": [73000, 40000], "width": 400, "height": 100 } - }, - "0b18429c-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18429c-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [73000, 40000], "end": [73000, 32000], "width": 400, "height": 100 } - }, - "0b18429d-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18429d-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [73000, 32000], "end": [72000, 32000], "width": 400, "height": 100 } - }, - "0b18429e-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18429e-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [72000, 32000], "end": [72000, 40000], "width": 400, "height": 100 } - }, - "0b18429f-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18429f-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [72000, 40000], "end": [71000, 40000], "width": 400, "height": 100 } - }, - "0b1842a0-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1842a0-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [71000, 40000], "end": [71000, 32000], "width": 400, "height": 100 } - }, - "0b1842a1-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1842a1-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [71000, 32000], "end": [70000, 32000], "width": 400, "height": 100 } - }, - "0b1842a2-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1842a2-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [70000, 32000], "end": [70000, 40000], "width": 400, "height": 100 } - }, - "0b1842a3-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1842a3-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [70000, 40000], "end": [69000, 40000], "width": 400, "height": 100 } - }, - "0b1842a4-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1842a4-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [69000, 40000], "end": [69000, 32000], "width": 400, "height": 100 } - }, - "0b1842a5-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1842a5-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [69000, 32000], "end": [68000, 32000], "width": 400, "height": 100 } - }, - "0b1842a6-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1842a6-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [68000, 32000], "end": [68000, 40000], "width": 400, "height": 100 } - }, - "0b1842a7-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1842a7-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [68000, 40000], "end": [67000, 40000], "width": 400, "height": 100 } - }, - "0b1842a8-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1842a8-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [67000, 40000], "end": [67000, 32000], "width": 400, "height": 100 } - }, - "0b1842a9-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1842a9-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [67000, 32000], "end": [51000, 32000], "width": 400, "height": 100 } - }, - "0b186980-3eff-11e5-93b5-5f17d678819e": { - "id": "0b186980-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [51000, 32000], "end": [51000, 34000], "width": 400, "height": 100 } - }, - "0b186981-3eff-11e5-93b5-5f17d678819e": { - "id": "0b186981-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [51000, 34000], "end": [60000, 38000], "width": 400, "height": 100 } - }, - "0b186982-3eff-11e5-93b5-5f17d678819e": { - "id": "0b186982-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [30000, 26000], "end": [20000, 26000], "width": 400, "height": 100 } - }, - "0b186983-3eff-11e5-93b5-5f17d678819e": { - "id": "0b186983-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [38000, 15000], "end": [38000, 21000], "width": 400, "height": 100 } - }, - "0b186984-3eff-11e5-93b5-5f17d678819e": { - "id": "0b186984-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [38000, 21000], "end": [39000, 22000], "width": 400, "height": 100 } - }, - "0b186985-3eff-11e5-93b5-5f17d678819e": { - "id": "0b186985-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [39000, 22000], "end": [44000, 22000], "width": 400, "height": 100 } - }, - "0b186986-3eff-11e5-93b5-5f17d678819e": { - "id": "0b186986-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [44000, 23000], "end": [30000, 23000], "width": 400, "height": 100 } - }, - "0b186987-3eff-11e5-93b5-5f17d678819e": { - "id": "0b186987-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [44000, 24000], "end": [30000, 24000], "width": 400, "height": 100 } - }, - "0b186988-3eff-11e5-93b5-5f17d678819e": { - "id": "0b186988-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [44000, 25000], "end": [30000, 25000], "width": 400, "height": 100 } - }, - "0b186989-3eff-11e5-93b5-5f17d678819e": { - "id": "0b186989-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [50000, 26000], "end": [49000, 27000], "width": 400, "height": 100 } - }, - "0b18698a-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18698a-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [50000, 26000], "end": [30000, 26000], "width": 400, "height": 100 } - }, - "0b18698b-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18698b-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [49000, 27000], "end": [30000, 27000], "width": 400, "height": 100 } - }, - "0b18698c-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18698c-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [50000, 28000], "end": [49000, 28000], "width": 400, "height": 100 } - }, - "0b18698d-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18698d-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [49000, 28000], "end": [45000, 28000], "width": 400, "height": 100 } - }, - "0b18698e-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18698e-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [50000, 28000], "end": [49000, 29000], "width": 400, "height": 100 } - }, - "0b18698f-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18698f-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [49000, 29000], "end": [45000, 29000], "width": 400, "height": 100 } - }, - "0b186990-3eff-11e5-93b5-5f17d678819e": { - "id": "0b186990-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [45000, 29000], "end": [45000, 29000], "width": 400, "height": 100 } - }, - "0b186991-3eff-11e5-93b5-5f17d678819e": { - "id": "0b186991-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [45000, 29000], "end": [39000, 35000], "width": 400, "height": 100 } - }, - "0b186992-3eff-11e5-93b5-5f17d678819e": { - "id": "0b186992-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [45000, 28000], "end": [39000, 34000], "width": 400, "height": 100 } - }, - "0b186993-3eff-11e5-93b5-5f17d678819e": { - "id": "0b186993-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [39000, 34000], "end": [38000, 34000], "width": 400, "height": 100 } - }, - "0b186994-3eff-11e5-93b5-5f17d678819e": { - "id": "0b186994-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [38000, 34000], "end": [38000, 33000], "width": 400, "height": 100 } - }, - "0b186995-3eff-11e5-93b5-5f17d678819e": { - "id": "0b186995-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [38000, 33000], "end": [39000, 33000], "width": 400, "height": 100 } - }, - "0b186996-3eff-11e5-93b5-5f17d678819e": { - "id": "0b186996-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [39000, 33000], "end": [43000, 29000], "width": 400, "height": 100 } - }, - "0b186997-3eff-11e5-93b5-5f17d678819e": { - "id": "0b186997-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [43000, 29000], "end": [43000, 28000], "width": 400, "height": 100 } - }, - "0b186998-3eff-11e5-93b5-5f17d678819e": { - "id": "0b186998-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [43000, 28000], "end": [42000, 28000], "width": 400, "height": 100 } - }, - "0b186999-3eff-11e5-93b5-5f17d678819e": { - "id": "0b186999-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [42000, 28000], "end": [42000, 29000], "width": 400, "height": 100 } - }, - "0b18699a-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18699a-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [42000, 29000], "end": [39000, 32000], "width": 400, "height": 100 } - }, - "0b18699b-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18699b-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [39000, 32000], "end": [38000, 32000], "width": 400, "height": 100 } - }, - "0b18699c-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18699c-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [38000, 32000], "end": [38000, 31000], "width": 400, "height": 100 } - }, - "0b18699d-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18699d-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [38000, 31000], "end": [39000, 31000], "width": 400, "height": 100 } - }, - "0b18699e-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18699e-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [39000, 31000], "end": [41000, 29000], "width": 400, "height": 100 } - }, - "0b18699f-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18699f-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [41000, 29000], "end": [41000, 28000], "width": 400, "height": 100 } - }, - "0b1869a0-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1869a0-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [41000, 28000], "end": [40000, 28000], "width": 400, "height": 100 } - }, - "0b1869a1-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1869a1-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [40000, 28000], "end": [40000, 29000], "width": 400, "height": 100 } - }, - "0b1869a2-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1869a2-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [40000, 29000], "end": [39000, 30000], "width": 400, "height": 100 } - }, - "0b1869a3-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1869a3-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [39000, 30000], "end": [38000, 30000], "width": 400, "height": 100 } - }, - "0b1869a4-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1869a4-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [38000, 30000], "end": [33000, 35000], "width": 400, "height": 100 } - }, - "0b1869a5-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1869a5-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [33000, 35000], "end": [20000, 35000], "width": 400, "height": 100 } - }, - "0b1869a6-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1869a6-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [20000, 35000], "end": [20000, 34000], "width": 400, "height": 100 } - }, - "0b1869a7-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1869a7-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [20000, 34000], "end": [25000, 34000], "width": 400, "height": 100 } - }, - "0b1869a8-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1869a8-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [25000, 34000], "end": [30000, 34000], "width": 400, "height": 100 } - }, - "0b1869a9-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1869a9-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [30000, 34000], "end": [30000, 33000], "width": 400, "height": 100 } - }, - "0b1869aa-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1869aa-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [30000, 33000], "end": [20000, 33000], "width": 400, "height": 100 } - }, - "0b1869ab-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1869ab-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [20000, 33000], "end": [20000, 32000], "width": 400, "height": 100 } - }, - "0b1869ac-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1869ac-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [20000, 32000], "end": [22000, 32000], "width": 400, "height": 100 } - }, - "0b1869ad-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1869ad-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [22000, 32000], "end": [22000, 30000], "width": 400, "height": 100 } - }, - "0b1869ae-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1869ae-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [22000, 30000], "end": [23000, 30000], "width": 400, "height": 100 } - }, - "0b1869af-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1869af-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [23000, 30000], "end": [23000, 32000], "width": 400, "height": 100 } - }, - "0b1869b0-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1869b0-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [23000, 32000], "end": [35000, 32000], "width": 400, "height": 100 } - }, - "0b1869b1-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1869b1-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [35000, 32000], "end": [37000, 30000], "width": 400, "height": 100 } - }, - "0b1869b2-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1869b2-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [37000, 30000], "end": [37000, 29000], "width": 400, "height": 100 } - }, - "0b1869b3-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1869b3-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [37000, 29000], "end": [31000, 29000], "width": 400, "height": 100 } - }, - "0b189090-3eff-11e5-93b5-5f17d678819e": { - "id": "0b189090-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [65000, 30000], "end": [52000, 30000], "width": 400, "height": 100 } - }, - "0b189091-3eff-11e5-93b5-5f17d678819e": { - "id": "0b189091-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [52000, 30000], "end": [51000, 31000], "width": 400, "height": 100 } - }, - "0b189092-3eff-11e5-93b5-5f17d678819e": { - "id": "0b189092-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [51000, 31000], "end": [50000, 31000], "width": 400, "height": 100 } - }, - "0b189093-3eff-11e5-93b5-5f17d678819e": { - "id": "0b189093-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [52000, 30000], "end": [49000, 30000], "width": 400, "height": 100 } - }, - "0b189094-3eff-11e5-93b5-5f17d678819e": { - "id": "0b189094-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [49000, 30000], "end": [49000, 42000], "width": 400, "height": 100 } - }, - "0b189095-3eff-11e5-93b5-5f17d678819e": { - "id": "0b189095-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [49000, 42000], "end": [48000, 42000], "width": 400, "height": 100 } - }, - "0b189096-3eff-11e5-93b5-5f17d678819e": { - "id": "0b189096-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [50000, 31000], "end": [50000, 45000], "width": 400, "height": 100 } - }, - "0b189097-3eff-11e5-93b5-5f17d678819e": { - "id": "0b189097-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [50000, 45000], "end": [48000, 47000], "width": 400, "height": 100 } - }, - "0b189098-3eff-11e5-93b5-5f17d678819e": { - "id": "0b189098-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [48000, 47000], "end": [6000, 47000], "width": 400, "height": 100 } - }, - "0b189099-3eff-11e5-93b5-5f17d678819e": { - "id": "0b189099-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [6000, 47000], "end": [4000, 45000], "width": 400, "height": 100 } - }, - "0b18909a-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18909a-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [4000, 45000], "end": [11000, 38000], "width": 400, "height": 100 } - }, - "0b18909b-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18909b-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [48000, 42000], "end": [48000, 32000], "width": 400, "height": 100 } - }, - "0b18909c-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18909c-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [48000, 32000], "end": [47000, 32000], "width": 400, "height": 100 } - }, - "0b18909d-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18909d-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [47000, 32000], "end": [47000, 43000], "width": 400, "height": 100 } - }, - "0b18909e-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18909e-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [47000, 43000], "end": [46000, 43000], "width": 400, "height": 100 } - }, - "0b18909f-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18909f-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [46000, 43000], "end": [46000, 33000], "width": 400, "height": 100 } - }, - "0b1890a0-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890a0-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [46000, 33000], "end": [45000, 33000], "width": 400, "height": 100 } - }, - "0b1890a1-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890a1-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [45000, 33000], "end": [45000, 43000], "width": 400, "height": 100 } - }, - "0b1890a2-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890a2-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [45000, 43000], "end": [44000, 43000], "width": 400, "height": 100 } - }, - "0b1890a3-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890a3-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [44000, 43000], "end": [44000, 34000], "width": 400, "height": 100 } - }, - "0b1890a4-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890a4-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [44000, 34000], "end": [43000, 34000], "width": 400, "height": 100 } - }, - "0b1890a5-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890a5-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [43000, 34000], "end": [43000, 43000], "width": 400, "height": 100 } - }, - "0b1890a6-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890a6-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [42000, 43000], "end": [42000, 43000], "width": 400, "height": 100 } - }, - "0b1890a7-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890a7-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [43000, 43000], "end": [42000, 43000], "width": 400, "height": 100 } - }, - "0b1890a8-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890a8-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [42000, 43000], "end": [42000, 38000], "width": 400, "height": 100 } - }, - "0b1890a9-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890a9-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [42000, 38000], "end": [41000, 38000], "width": 400, "height": 100 } - }, - "0b1890aa-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890aa-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [41000, 38000], "end": [41000, 45000], "width": 400, "height": 100 } - }, - "0b1890ab-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890ab-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [41000, 45000], "end": [35000, 45000], "width": 400, "height": 100 } - }, - "0b1890ac-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890ac-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [35000, 45000], "end": [30000, 40000], "width": 400, "height": 100 } - }, - "0b1890ad-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890ad-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [9000, 41000], "end": [10000, 40000], "width": 400, "height": 100 } - }, - "0b1890ae-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890ae-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [9000, 40000], "end": [12000, 37000], "width": 400, "height": 100 } - }, - "0b1890af-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890af-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [12000, 37000], "end": [24000, 37000], "width": 400, "height": 100 } - }, - "0b1890b0-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890b0-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [24000, 37000], "end": [24000, 36000], "width": 400, "height": 100 } - }, - "0b1890b1-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890b1-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [24000, 36000], "end": [12000, 36000], "width": 400, "height": 100 } - }, - "0b1890b2-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890b2-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [12000, 36000], "end": [21000, 27000], "width": 400, "height": 100 } - }, - "0b1890b3-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890b3-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [21000, 27000], "end": [30000, 27000], "width": 400, "height": 100 } - }, - "0b1890b4-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890b4-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [20000, 26000], "end": [9000, 37000], "width": 400, "height": 100 } - }, - "0b1890b5-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890b5-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [9000, 37000], "end": [3000, 37000], "width": 400, "height": 100 } - }, - "0b1890b6-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890b6-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [3000, 37000], "end": [3000, 36000], "width": 400, "height": 100 } - }, - "0b1890b7-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890b7-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [3000, 36000], "end": [8000, 36000], "width": 400, "height": 100 } - }, - "0b1890b8-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890b8-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [8000, 36000], "end": [9000, 36000], "width": 400, "height": 100 } - }, - "0b1890b9-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890b9-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [9000, 36000], "end": [9000, 35000], "width": 400, "height": 100 } - }, - "0b1890ba-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890ba-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [9000, 35000], "end": [3000, 35000], "width": 400, "height": 100 } - }, - "0b1890bb-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890bb-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [3000, 35000], "end": [3000, 34000], "width": 400, "height": 100 } - }, - "0b1890bc-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890bc-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [3000, 34000], "end": [9000, 34000], "width": 400, "height": 100 } - }, - "0b1890bd-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890bd-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [9000, 34000], "end": [9000, 33000], "width": 400, "height": 100 } - }, - "0b1890be-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890be-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [9000, 33000], "end": [3000, 33000], "width": 400, "height": 100 } - }, - "0b1890bf-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890bf-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [3000, 33000], "end": [3000, 32000], "width": 400, "height": 100 } - }, - "0b1890c0-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890c0-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [3000, 32000], "end": [12000, 32000], "width": 400, "height": 100 } - }, - "0b1890c1-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890c1-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [12000, 32000], "end": [16000, 28000], "width": 400, "height": 100 } - }, - "0b1890c2-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890c2-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [16000, 28000], "end": [16000, 26000], "width": 400, "height": 100 } - }, - "0b1890c3-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890c3-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [16000, 26000], "end": [5000, 26000], "width": 400, "height": 100 } - }, - "0b1890c4-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890c4-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [5000, 26000], "end": [4000, 27000], "width": 400, "height": 100 } - }, - "0b1890c5-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890c5-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [4000, 27000], "end": [9000, 30000], "width": 400, "height": 100 } - }, - "0b1890c6-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890c6-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [39000, 35000], "end": [39000, 43000], "width": 400, "height": 100 } - }, - "0b1890c7-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890c7-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [39000, 43000], "end": [38000, 43000], "width": 400, "height": 100 } - }, - "0b1890c8-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890c8-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [38000, 43000], "end": [38000, 36000], "width": 400, "height": 100 } - }, - "0b1890c9-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890c9-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [38000, 36000], "end": [28000, 36000], "width": 400, "height": 100 } - }, - "0b1890ca-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890ca-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [28000, 36000], "end": [24000, 40000], "width": 400, "height": 100 } - }, - "0b1890cb-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890cb-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [24000, 40000], "end": [24000, 45000], "width": 400, "height": 100 } - }, - "0b1890cc-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890cc-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [24000, 45000], "end": [15000, 45000], "width": 400, "height": 100 } - }, - "0b1890cd-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890cd-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [15000, 45000], "end": [10000, 40000], "width": 400, "height": 100 } - }, - "0b1890ce-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890ce-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [57000, 8000], "end": [56000, 9000], "width": 400, "height": 100 } - }, - "0b1890cf-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890cf-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [56000, 9000], "end": [56000, 10000], "width": 400, "height": 100 } - }, - "0b1890d0-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890d0-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [56000, 10000], "end": [62000, 16000], "width": 400, "height": 100 } - }, - "0b1890d1-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890d1-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [62000, 16000], "end": [62000, 17000], "width": 400, "height": 100 } - }, - "0b1890d2-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890d2-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [63000, 17000], "end": [63000, 15000], "width": 400, "height": 100 } - }, - "0b1890d3-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890d3-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [63000, 15000], "end": [63000, 15000], "width": 400, "height": 100 } - }, - "0b1890d4-3eff-11e5-93b5-5f17d678819e": { - "id": "0b1890d4-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [63000, 15000], "end": [59000, 11000], "width": 400, "height": 100 } - }, - "0b18b7a0-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18b7a0-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [59000, 11000], "end": [58000, 10000], "width": 400, "height": 100 } - }, - "0b18b7a1-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18b7a1-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [58000, 10000], "end": [58000, 9000], "width": 400, "height": 100 } - }, - "0b18b7a2-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18b7a2-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [59000, 3000], "end": [66000, 10000], "width": 400, "height": 100 } - }, - "0b18b7a3-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18b7a3-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [61000, 7000], "end": [60000, 7000], "width": 400, "height": 100 } - }, - "0b18b7a4-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18b7a4-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [59000, 9000], "end": [61000, 9000], "width": 400, "height": 100 } - }, - "0b18b7a5-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18b7a5-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [58000, 9000], "end": [59000, 9000], "width": 400, "height": 100 } - }, - "0b18b7a6-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18b7a6-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [61000, 9000], "end": [61000, 7000], "width": 400, "height": 100 } - }, - "0b18b7a7-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18b7a7-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [62000, 7000], "end": [62000, 10000], "width": 400, "height": 100 } - }, - "0b18b7a8-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18b7a8-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [62000, 10000], "end": [64000, 12000], "width": 400, "height": 100 } - }, - "0b18b7a9-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18b7a9-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [64000, 12000], "end": [64000, 17000], "width": 400, "height": 100 } - }, - "0b18b7aa-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18b7aa-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [54000, 4000], "end": [62000, 6000], "width": 400, "height": 100 } - }, - "0b18b7ab-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18b7ab-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [55000, 6000], "end": [54000, 7000], "width": 400, "height": 100 } - }, - "0b18b7ac-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18b7ac-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [54000, 7000], "end": [54000, 10000], "width": 400, "height": 100 } - }, - "0b18b7ad-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18b7ad-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [55000, 6000], "end": [60000, 6000], "width": 400, "height": 100 } - }, - "0b18b7ae-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18b7ae-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [54000, 4000], "end": [53000, 5000], "width": 400, "height": 100 } - }, - "0b18b7af-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18b7af-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [57000, 8000], "end": [59000, 8000], "width": 400, "height": 100 } - }, - "0b18b7b0-3eff-11e5-93b5-5f17d678819e": { - "id": "0b18b7b0-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [59000, 8000], "end": [61000, 6000], "width": 400, "height": 100 } - } - } - }, - { - "name": "control", - "color": "red", - "params": { "z_offset": 1200, "flip": true }, - "features": { - "387e92f0-3eff-11e5-93b5-5f17d678819e": { - "id": "387e92f0-3eff-11e5-93b5-5f17d678819e", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [52000, 19000], "end": [53000, 21000], "borderWidth": 400, "height": 100 } - }, - "3be3b6f0-3eff-11e5-93b5-5f17d678819e": { - "id": "3be3b6f0-3eff-11e5-93b5-5f17d678819e", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [54000, 21000], "end": [55000, 23000], "borderWidth": 400, "height": 100 } - }, - "3cf61150-3eff-11e5-93b5-5f17d678819e": { - "id": "3cf61150-3eff-11e5-93b5-5f17d678819e", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [56000, 23000], "end": [57000, 25000], "borderWidth": 400, "height": 100 } - }, - "3dc659a0-3eff-11e5-93b5-5f17d678819e": { - "id": "3dc659a0-3eff-11e5-93b5-5f17d678819e", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [58000, 25000], "end": [59000, 27000], "borderWidth": 400, "height": 100 } - }, - "3ea45d90-3eff-11e5-93b5-5f17d678819e": { - "id": "3ea45d90-3eff-11e5-93b5-5f17d678819e", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [60000, 27000], "end": [61000, 29000], "borderWidth": 400, "height": 100 } - }, - "3f5cb110-3eff-11e5-93b5-5f17d678819e": { - "id": "3f5cb110-3eff-11e5-93b5-5f17d678819e", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [62000, 29000], "end": [63000, 31000], "borderWidth": 400, "height": 100 } - }, - "47eb6560-3eff-11e5-93b5-5f17d678819e": { - "id": "47eb6560-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [52500, 16000], "end": [52500, 20000], "width": 400, "height": 100 } - }, - "4b52d350-3eff-11e5-93b5-5f17d678819e": { - "id": "4b52d350-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [54500, 22000], "end": [54500, 17000], "width": 400, "height": 100 } - }, - "4f8f4480-3eff-11e5-93b5-5f17d678819e": { - "id": "4f8f4480-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [56500, 23600], "end": [56500, 18000], "width": 400, "height": 100 } - }, - "55756e10-3eff-11e5-93b5-5f17d678819e": { - "id": "55756e10-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [58500, 26000], "end": [58500, 22200], "width": 400, "height": 100 } - }, - "571402e0-3eff-11e5-93b5-5f17d678819e": { - "id": "571402e0-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [58500, 22100], "end": [58500, 19200], "width": 400, "height": 100 } - }, - "592a11a0-3eff-11e5-93b5-5f17d678819e": { - "id": "592a11a0-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [58500, 19200], "end": [58500, 19000], "width": 400, "height": 100 } - }, - "5c7df790-3eff-11e5-93b5-5f17d678819e": { - "id": "5c7df790-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [60500, 20000], "end": [60500, 20400], "width": 400, "height": 100 } - }, - "5e7d7110-3eff-11e5-93b5-5f17d678819e": { - "id": "5e7d7110-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [60500, 20500], "end": [60500, 24900], "width": 400, "height": 100 } - }, - "60abe9d0-3eff-11e5-93b5-5f17d678819e": { - "id": "60abe9d0-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [60500, 25000], "end": [60500, 27800], "width": 400, "height": 100 } - }, - "64abc730-3eff-11e5-93b5-5f17d678819e": { - "id": "64abc730-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [62500, 29000], "end": [62500, 23600], "width": 400, "height": 100 } - }, - "670aece0-3eff-11e5-93b5-5f17d678819e": { - "id": "670aece0-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [62500, 23600], "end": [62500, 21000], "width": 400, "height": 100 } - }, - "6b44ed10-3eff-11e5-93b5-5f17d678819e": { - "id": "6b44ed10-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [52500, 16000], "end": [53000, 16000], "width": 400, "height": 100 } - }, - "6cfe35d0-3eff-11e5-93b5-5f17d678819e": { - "id": "6cfe35d0-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [54500, 17000], "end": [55000, 17000], "width": 400, "height": 100 } - }, - "6e748220-3eff-11e5-93b5-5f17d678819e": { - "id": "6e748220-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [56500, 18000], "end": [57000, 18000], "width": 400, "height": 100 } - }, - "6f704740-3eff-11e5-93b5-5f17d678819e": { - "id": "6f704740-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [58500, 19000], "end": [59000, 19000], "width": 400, "height": 100 } - }, - "723a8ad0-3eff-11e5-93b5-5f17d678819e": { - "id": "723a8ad0-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [62500, 21000], "end": [63000, 21000], "width": 400, "height": 100 } - }, - "9a3fc040-3eff-11e5-93b5-5f17d678819e": { - "id": "9a3fc040-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [53000, 16000], "end": [66000, 16000], "width": 400, "height": 100 } - }, - "9b18e230-3eff-11e5-93b5-5f17d678819e": { - "id": "9b18e230-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [55000, 17000], "end": [66000, 17000], "width": 400, "height": 100 } - }, - "9bbaee90-3eff-11e5-93b5-5f17d678819e": { - "id": "9bbaee90-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [57000, 18000], "end": [66000, 18000], "width": 400, "height": 100 } - }, - "9c5c5eb0-3eff-11e5-93b5-5f17d678819e": { - "id": "9c5c5eb0-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [59000, 19000], "end": [66000, 19000], "width": 400, "height": 100 } - }, - "a0b90210-3eff-11e5-93b5-5f17d678819e": { - "id": "a0b90210-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [60000, 20000], "end": [66000, 20000], "width": 400, "height": 100 } - }, - "a1663200-3eff-11e5-93b5-5f17d678819e": { - "id": "a1663200-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [63000, 21000], "end": [66000, 21000], "width": 400, "height": 100 } - }, - "a2535120-3eff-11e5-93b5-5f17d678819e": { - "id": "a2535120-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [66000, 21000], "end": [67000, 22000], "width": 400, "height": 100 } - }, - "a3910140-3eff-11e5-93b5-5f17d678819e": { - "id": "a3910140-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [66000, 20000], "end": [67000, 20000], "width": 400, "height": 100 } - }, - "a47064c0-3eff-11e5-93b5-5f17d678819e": { - "id": "a47064c0-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [67000, 20000], "end": [69000, 22000], "width": 400, "height": 100 } - }, - "a5548330-3eff-11e5-93b5-5f17d678819e": { - "id": "a5548330-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [66000, 19000], "end": [67000, 19000], "width": 400, "height": 100 } - }, - "a6fc3fc0-3eff-11e5-93b5-5f17d678819e": { - "id": "a6fc3fc0-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [67000, 19000], "end": [68000, 19000], "width": 400, "height": 100 } - }, - "a75e35e0-3eff-11e5-93b5-5f17d678819e": { - "id": "a75e35e0-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [68000, 19000], "end": [71000, 22000], "width": 400, "height": 100 } - }, - "a8d98b40-3eff-11e5-93b5-5f17d678819e": { - "id": "a8d98b40-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [66000, 18000], "end": [69000, 18000], "width": 400, "height": 100 } - }, - "a96158e0-3eff-11e5-93b5-5f17d678819e": { - "id": "a96158e0-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [69000, 18000], "end": [71000, 20000], "width": 400, "height": 100 } - }, - "ac244970-3eff-11e5-93b5-5f17d678819e": { - "id": "ac244970-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [66000, 17000], "end": [70000, 17000], "width": 400, "height": 100 } - }, - "ac990440-3eff-11e5-93b5-5f17d678819e": { - "id": "ac990440-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [70000, 17000], "end": [71000, 18000], "width": 400, "height": 100 } - }, - "ae167c80-3eff-11e5-93b5-5f17d678819e": { - "id": "ae167c80-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [66000, 16000], "end": [71000, 16000], "width": 400, "height": 100 } - }, - "b0b6c9e0-3eff-11e5-93b5-5f17d678819e": { - "id": "b0b6c9e0-3eff-11e5-93b5-5f17d678819e", - "name": "New Port", - "type": "Port", - "params": { "position": [67000, 22000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "b11c9090-3eff-11e5-93b5-5f17d678819e": { - "id": "b11c9090-3eff-11e5-93b5-5f17d678819e", - "name": "New Port", - "type": "Port", - "params": { "position": [69000, 22000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "b1767060-3eff-11e5-93b5-5f17d678819e": { - "id": "b1767060-3eff-11e5-93b5-5f17d678819e", - "name": "New Port", - "type": "Port", - "params": { "position": [71000, 22000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "b1bfd570-3eff-11e5-93b5-5f17d678819e": { - "id": "b1bfd570-3eff-11e5-93b5-5f17d678819e", - "name": "New Port", - "type": "Port", - "params": { "position": [71000, 20000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "b21632d0-3eff-11e5-93b5-5f17d678819e": { - "id": "b21632d0-3eff-11e5-93b5-5f17d678819e", - "name": "New Port", - "type": "Port", - "params": { "position": [71000, 18000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "b25e3850-3eff-11e5-93b5-5f17d678819e": { - "id": "b25e3850-3eff-11e5-93b5-5f17d678819e", - "name": "New Port", - "type": "Port", - "params": { "position": [71000, 16000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "c04f1920-3eff-11e5-93b5-5f17d678819e": { - "id": "c04f1920-3eff-11e5-93b5-5f17d678819e", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [9000, 9000], "end": [10000, 10000], "borderWidth": 400, "height": 100 } - }, - "c10a2bc0-3eff-11e5-93b5-5f17d678819e": { - "id": "c10a2bc0-3eff-11e5-93b5-5f17d678819e", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [9000, 19000], "end": [10000, 20000], "borderWidth": 400, "height": 100 } - }, - "c1a58160-3eff-11e5-93b5-5f17d678819e": { - "id": "c1a58160-3eff-11e5-93b5-5f17d678819e", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [9000, 29000], "end": [10000, 30000], "borderWidth": 400, "height": 100 } - }, - "c243bd30-3eff-11e5-93b5-5f17d678819e": { - "id": "c243bd30-3eff-11e5-93b5-5f17d678819e", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [9000, 39000], "end": [10000, 40000], "borderWidth": 400, "height": 100 } - }, - "c31c9100-3eff-11e5-93b5-5f17d678819e": { - "id": "c31c9100-3eff-11e5-93b5-5f17d678819e", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [29000, 9000], "end": [30000, 10000], "borderWidth": 400, "height": 100 } - }, - "c3bcefb0-3eff-11e5-93b5-5f17d678819e": { - "id": "c3bcefb0-3eff-11e5-93b5-5f17d678819e", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [29000, 19000], "end": [30000, 20000], "borderWidth": 400, "height": 100 } - }, - "c4780250-3eff-11e5-93b5-5f17d678819e": { - "id": "c4780250-3eff-11e5-93b5-5f17d678819e", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [29000, 29000], "end": [30000, 30000], "borderWidth": 400, "height": 100 } - }, - "c532c6d0-3eff-11e5-93b5-5f17d678819e": { - "id": "c532c6d0-3eff-11e5-93b5-5f17d678819e", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [29000, 39000], "end": [30000, 40000], "borderWidth": 400, "height": 100 } - }, - "c65267a0-3eff-11e5-93b5-5f17d678819e": { - "id": "c65267a0-3eff-11e5-93b5-5f17d678819e", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [61000, 39000], "end": [62000, 40000], "borderWidth": 400, "height": 100 } - }, - "c725e440-3eff-11e5-93b5-5f17d678819e": { - "id": "c725e440-3eff-11e5-93b5-5f17d678819e", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [61000, 5000], "end": [62000, 6000], "borderWidth": 400, "height": 100 } - }, - "fb551d30-3eff-11e5-93b5-5f17d678819e": { - "id": "fb551d30-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [9600, 9500], "end": [25000, 9500], "width": 400, "height": 100 } - }, - "ff6db2b0-3eff-11e5-93b5-5f17d678819e": { - "id": "ff6db2b0-3eff-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [25000, 9500], "end": [27300, 9500], "width": 400, "height": 100 } - }, - "007314c0-3f00-11e5-93b5-5f17d678819e": { - "id": "007314c0-3f00-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [27300, 9500], "end": [29200, 9500], "width": 400, "height": 100 } - }, - "02b2a480-3f00-11e5-93b5-5f17d678819e": { - "id": "02b2a480-3f00-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [9500, 19500], "end": [21600, 19600], "width": 400, "height": 100 } - }, - "056c4640-3f00-11e5-93b5-5f17d678819e": { - "id": "056c4640-3f00-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [21600, 19600], "end": [29600, 19600], "width": 400, "height": 100 } - }, - "09610010-3f00-11e5-93b5-5f17d678819e": { - "id": "09610010-3f00-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [9500, 29500], "end": [24100, 29500], "width": 400, "height": 100 } - }, - "0da25340-3f00-11e5-93b5-5f17d678819e": { - "id": "0da25340-3f00-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [24200, 29500], "end": [29500, 29500], "width": 400, "height": 100 } - }, - "10cba6c0-3f00-11e5-93b5-5f17d678819e": { - "id": "10cba6c0-3f00-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [9500, 39500], "end": [19500, 39500], "width": 400, "height": 100 } - }, - "137039e0-3f00-11e5-93b5-5f17d678819e": { - "id": "137039e0-3f00-11e5-93b5-5f17d678819e", - "name": "New Channel", - "type": "Channel", - "params": { "start": [19500, 39500], "end": [29600, 39500], "width": 400, "height": 100 } - } - } - } - ], - "groups": [], - "defaults": {} -} diff --git a/examples/VoigtCassieMockup.json b/examples/VoigtCassieMockup.json deleted file mode 100644 index 10bf75e6..00000000 --- a/examples/VoigtCassieMockup.json +++ /dev/null @@ -1,1900 +0,0 @@ -{ - "name": "My Device", - "params": { "width": 75800, "height": 51000 }, - "layers": [ - { - "name": "flow", - "color": "indigo", - "params": { "z_offset": 0, "flip": false }, - "features": { - "3238de90-404f-11e5-877d-e53327a933d0": { - "id": "3238de90-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [2000, 40000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "323905a0-404f-11e5-877d-e53327a933d0": { - "id": "323905a0-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [2000, 35000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "323905a1-404f-11e5-877d-e53327a933d0": { - "id": "323905a1-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [2000, 30000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "323905a2-404f-11e5-877d-e53327a933d0": { - "id": "323905a2-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [2000, 25000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "323905a3-404f-11e5-877d-e53327a933d0": { - "id": "323905a3-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [2000, 20000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "323905a4-404f-11e5-877d-e53327a933d0": { - "id": "323905a4-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [2000, 15000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "323905a5-404f-11e5-877d-e53327a933d0": { - "id": "323905a5-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [2000, 10000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "323905a6-404f-11e5-877d-e53327a933d0": { - "id": "323905a6-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [2000, 5000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "32392cb0-404f-11e5-877d-e53327a933d0": { - "id": "32392cb0-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [2000, 5000], "end": [10000, 5000], "width": 410, "height": 100 } - }, - "32392cb1-404f-11e5-877d-e53327a933d0": { - "id": "32392cb1-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [10000, 5000], "end": [10000, 10000], "width": 410, "height": 100 } - }, - "32392cb2-404f-11e5-877d-e53327a933d0": { - "id": "32392cb2-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [2000, 10000], "end": [10000, 10000], "width": 410, "height": 100 } - }, - "32392cb3-404f-11e5-877d-e53327a933d0": { - "id": "32392cb3-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [10000, 7500], "end": [13000, 7500], "width": 410, "height": 100 } - }, - "32392cb4-404f-11e5-877d-e53327a933d0": { - "id": "32392cb4-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [13000, 7500], "end": [13000, 11700], "width": 410, "height": 100 } - }, - "32392cb5-404f-11e5-877d-e53327a933d0": { - "id": "32392cb5-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [13000, 11000], "end": [13000, 17000], "width": 410, "height": 100 } - }, - "32392cb6-404f-11e5-877d-e53327a933d0": { - "id": "32392cb6-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [13000, 17000], "end": [13000, 17500], "width": 410, "height": 100 } - }, - "32392cb7-404f-11e5-877d-e53327a933d0": { - "id": "32392cb7-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [2000, 15000], "end": [10000, 15000], "width": 410, "height": 100 } - }, - "32392cb8-404f-11e5-877d-e53327a933d0": { - "id": "32392cb8-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [10000, 15000], "end": [10000, 20000], "width": 410, "height": 100 } - }, - "323953c0-404f-11e5-877d-e53327a933d0": { - "id": "323953c0-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [10000, 20000], "end": [2000, 20000], "width": 410, "height": 100 } - }, - "323953c1-404f-11e5-877d-e53327a933d0": { - "id": "323953c1-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [13000, 17500], "end": [10000, 17500], "width": 410, "height": 100 } - }, - "323953c2-404f-11e5-877d-e53327a933d0": { - "id": "323953c2-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [2000, 25000], "end": [10000, 25000], "width": 410, "height": 100 } - }, - "323953c3-404f-11e5-877d-e53327a933d0": { - "id": "323953c3-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [10000, 25000], "end": [10000, 25000], "width": 410, "height": 100 } - }, - "323953c4-404f-11e5-877d-e53327a933d0": { - "id": "323953c4-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [2000, 30000], "end": [10000, 30000], "width": 410, "height": 100 } - }, - "323953c5-404f-11e5-877d-e53327a933d0": { - "id": "323953c5-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [2000, 35000], "end": [10000, 35000], "width": 410, "height": 100 } - }, - "323953c6-404f-11e5-877d-e53327a933d0": { - "id": "323953c6-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [2000, 40000], "end": [10000, 40000], "width": 410, "height": 100 } - }, - "323953c7-404f-11e5-877d-e53327a933d0": { - "id": "323953c7-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [10000, 25000], "end": [10000, 30000], "width": 410, "height": 100 } - }, - "323953c8-404f-11e5-877d-e53327a933d0": { - "id": "323953c8-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [10000, 35000], "end": [10000, 40000], "width": 410, "height": 100 } - }, - "32397ad0-404f-11e5-877d-e53327a933d0": { - "id": "32397ad0-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [13000, 12500], "end": [16000, 12500], "width": 410, "height": 100 } - }, - "32397ad1-404f-11e5-877d-e53327a933d0": { - "id": "32397ad1-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [16000, 12500], "end": [16000, 13000], "width": 410, "height": 100 } - }, - "32397ad2-404f-11e5-877d-e53327a933d0": { - "id": "32397ad2-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [16000, 22500], "end": [18000, 22500], "width": 410, "height": 100 } - }, - "32397ad3-404f-11e5-877d-e53327a933d0": { - "id": "32397ad3-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [18000, 22500], "end": [20000, 22500], "width": 410, "height": 100 } - }, - "32397ad4-404f-11e5-877d-e53327a933d0": { - "id": "32397ad4-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [20000, 22500], "end": [20000, 22000], "width": 410, "height": 100 } - }, - "32397ad5-404f-11e5-877d-e53327a933d0": { - "id": "32397ad5-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [20000, 22500], "end": [20000, 23000], "width": 410, "height": 100 } - }, - "32397ad6-404f-11e5-877d-e53327a933d0": { - "id": "32397ad6-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [20000, 22000], "end": [20000, 11000], "width": 410, "height": 100 } - }, - "32397ad7-404f-11e5-877d-e53327a933d0": { - "id": "32397ad7-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [20000, 11000], "end": [25000, 11000], "width": 410, "height": 100 } - }, - "3239a1e0-404f-11e5-877d-e53327a933d0": { - "id": "3239a1e0-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [20000, 23000], "end": [20000, 34000], "width": 410, "height": 100 } - }, - "3239a1e1-404f-11e5-877d-e53327a933d0": { - "id": "3239a1e1-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [20000, 34000], "end": [25000, 34000], "width": 410, "height": 100 } - }, - "3239a1e2-404f-11e5-877d-e53327a933d0": { - "id": "3239a1e2-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [25000, 11000], "end": [25000, 11000], "width": 410, "height": 100 } - }, - "3239a1e3-404f-11e5-877d-e53327a933d0": { - "id": "3239a1e3-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [25000, 11000], "end": [25000, 5000], "width": 410, "height": 100 } - }, - "3239a1e4-404f-11e5-877d-e53327a933d0": { - "id": "3239a1e4-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [25000, 11000], "end": [25000, 17000], "width": 410, "height": 100 } - }, - "3239a1e5-404f-11e5-877d-e53327a933d0": { - "id": "3239a1e5-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [25000, 5000], "end": [45000, 5000], "width": 410, "height": 100 } - }, - "3239a1e6-404f-11e5-877d-e53327a933d0": { - "id": "3239a1e6-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [45000, 5000], "end": [45000, 17000], "width": 410, "height": 100 } - }, - "3239a1e7-404f-11e5-877d-e53327a933d0": { - "id": "3239a1e7-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [45000, 17000], "end": [25000, 17000], "width": 410, "height": 100 } - }, - "3239a1e8-404f-11e5-877d-e53327a933d0": { - "id": "3239a1e8-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [25000, 34000], "end": [25000, 40000], "width": 410, "height": 100 } - }, - "3239a1e9-404f-11e5-877d-e53327a933d0": { - "id": "3239a1e9-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [25000, 34000], "end": [25000, 28000], "width": 410, "height": 100 } - }, - "3239c8f0-404f-11e5-877d-e53327a933d0": { - "id": "3239c8f0-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [25000, 28000], "end": [45000, 28000], "width": 410, "height": 100 } - }, - "3239c8f1-404f-11e5-877d-e53327a933d0": { - "id": "3239c8f1-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [45000, 28000], "end": [45000, 40000], "width": 410, "height": 100 } - }, - "3239c8f2-404f-11e5-877d-e53327a933d0": { - "id": "3239c8f2-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [45000, 40000], "end": [25000, 40000], "width": 410, "height": 100 } - }, - "3239c8f3-404f-11e5-877d-e53327a933d0": { - "id": "3239c8f3-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [30000, 17000], "end": [30000, 10000], "width": 410, "height": 100 } - }, - "3239c8f4-404f-11e5-877d-e53327a933d0": { - "id": "3239c8f4-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [40000, 17000], "end": [40000, 10000], "width": 410, "height": 100 } - }, - "3239c8f5-404f-11e5-877d-e53327a933d0": { - "id": "3239c8f5-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [30000, 10000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "3239c8f6-404f-11e5-877d-e53327a933d0": { - "id": "3239c8f6-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [40000, 10000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "3239c8f7-404f-11e5-877d-e53327a933d0": { - "id": "3239c8f7-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [30000, 28000], "end": [30000, 35000], "width": 410, "height": 100 } - }, - "3239f000-404f-11e5-877d-e53327a933d0": { - "id": "3239f000-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [40000, 28000], "end": [40000, 35000], "width": 410, "height": 100 } - }, - "3239f001-404f-11e5-877d-e53327a933d0": { - "id": "3239f001-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [30000, 35000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "3239f002-404f-11e5-877d-e53327a933d0": { - "id": "3239f002-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [40000, 35000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "3239f003-404f-11e5-877d-e53327a933d0": { - "id": "3239f003-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [10000, 27500], "end": [13000, 27500], "width": 410, "height": 100 } - }, - "3239f004-404f-11e5-877d-e53327a933d0": { - "id": "3239f004-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [10000, 37500], "end": [13000, 37500], "width": 410, "height": 100 } - }, - "3239f005-404f-11e5-877d-e53327a933d0": { - "id": "3239f005-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [13000, 37500], "end": [13000, 37000], "width": 410, "height": 100 } - }, - "3239f006-404f-11e5-877d-e53327a933d0": { - "id": "3239f006-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [13000, 27500], "end": [13000, 28000], "width": 410, "height": 100 } - }, - "3239f007-404f-11e5-877d-e53327a933d0": { - "id": "3239f007-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [13000, 28000], "end": [13000, 37000], "width": 410, "height": 100 } - }, - "3239f008-404f-11e5-877d-e53327a933d0": { - "id": "3239f008-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [13000, 32500], "end": [16000, 32500], "width": 410, "height": 100 } - }, - "323a1710-404f-11e5-877d-e53327a933d0": { - "id": "323a1710-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [16000, 32500], "end": [16000, 31000], "width": 410, "height": 100 } - }, - "323a1711-404f-11e5-877d-e53327a933d0": { - "id": "323a1711-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [16000, 31000], "end": [16000, 22000], "width": 410, "height": 100 } - }, - "323a1712-404f-11e5-877d-e53327a933d0": { - "id": "323a1712-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [16000, 22000], "end": [16000, 13000], "width": 410, "height": 100 } - }, - "323a1713-404f-11e5-877d-e53327a933d0": { - "id": "323a1713-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [20000, 22500], "end": [29000, 22500], "width": 410, "height": 100 } - }, - "323a1714-404f-11e5-877d-e53327a933d0": { - "id": "323a1714-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [30000, 22600], "end": [30000, 23000], "width": 410, "height": 100 } - }, - "323a1715-404f-11e5-877d-e53327a933d0": { - "id": "323a1715-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [40000, 17000], "end": [40000, 28000], "width": 410, "height": 100 } - }, - "323a1716-404f-11e5-877d-e53327a933d0": { - "id": "323a1716-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [30000, 22500], "end": [40000, 22500], "width": 410, "height": 100 } - }, - "323a1717-404f-11e5-877d-e53327a933d0": { - "id": "323a1717-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [30000, 17000], "end": [30000, 28000], "width": 410, "height": 100 } - }, - "323a1718-404f-11e5-877d-e53327a933d0": { - "id": "323a1718-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [29000, 22500], "end": [30000, 22500], "width": 410, "height": 100 } - }, - "323a3e20-404f-11e5-877d-e53327a933d0": { - "id": "323a3e20-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [35000, 17000], "end": [35000, 28000], "width": 410, "height": 100 } - } - } - }, - { - "name": "control", - "color": "red", - "params": { "z_offset": 500, "flip": true }, - "features": { - "323a3e21-404f-11e5-877d-e53327a933d0": { - "id": "323a3e21-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [9000, 9000], "end": [9000, 11000], "width": 50, "height": 100 } - }, - "323a3e22-404f-11e5-877d-e53327a933d0": { - "id": "323a3e22-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [9000, 19000], "end": [9000, 21000], "width": 50, "height": 100 } - }, - "323a3e23-404f-11e5-877d-e53327a933d0": { - "id": "323a3e23-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [9000, 29000], "end": [9000, 31000], "width": 50, "height": 100 } - }, - "323a3e24-404f-11e5-877d-e53327a933d0": { - "id": "323a3e24-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [11000, 26600], "end": [11000, 28500], "width": 50, "height": 100 } - }, - "323a3e25-404f-11e5-877d-e53327a933d0": { - "id": "323a3e25-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [12000, 18500], "end": [12000, 16500], "width": 50, "height": 100 } - }, - "323a3e26-404f-11e5-877d-e53327a933d0": { - "id": "323a3e26-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [24000, 10000], "end": [24000, 12000], "width": 50, "height": 100 } - }, - "323a3e27-404f-11e5-877d-e53327a933d0": { - "id": "323a3e27-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [39000, 14000], "end": [41000, 14000], "width": 50, "height": 100 } - }, - "323a6530-404f-11e5-877d-e53327a933d0": { - "id": "323a6530-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [29000, 12000], "end": [31000, 12000], "width": 50, "height": 100 } - }, - "323a6531-404f-11e5-877d-e53327a933d0": { - "id": "323a6531-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [39000, 12000], "end": [41000, 12000], "width": 50, "height": 100 } - }, - "323a6532-404f-11e5-877d-e53327a933d0": { - "id": "323a6532-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [39000, 13000], "end": [41000, 13000], "width": 50, "height": 100 } - }, - "323a6533-404f-11e5-877d-e53327a933d0": { - "id": "323a6533-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [39000, 15000], "end": [41000, 15000], "width": 50, "height": 100 } - }, - "323a6534-404f-11e5-877d-e53327a933d0": { - "id": "323a6534-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [39000, 19000], "end": [41000, 19000], "width": 50, "height": 100 } - }, - "323a6535-404f-11e5-877d-e53327a933d0": { - "id": "323a6535-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [39000, 20000], "end": [41000, 20000], "width": 50, "height": 100 } - }, - "323a6536-404f-11e5-877d-e53327a933d0": { - "id": "323a6536-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [34000, 19000], "end": [36000, 19000], "width": 50, "height": 100 } - }, - "323a6537-404f-11e5-877d-e53327a933d0": { - "id": "323a6537-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [34000, 21000], "end": [36000, 21000], "width": 50, "height": 100 } - }, - "323a6538-404f-11e5-877d-e53327a933d0": { - "id": "323a6538-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [44000, 12000], "end": [46000, 12000], "width": 50, "height": 100 } - }, - "323a8c40-404f-11e5-877d-e53327a933d0": { - "id": "323a8c40-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [44000, 13000], "end": [46000, 13000], "width": 50, "height": 100 } - }, - "323a8c41-404f-11e5-877d-e53327a933d0": { - "id": "323a8c41-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [44000, 14000], "end": [46000, 14000], "width": 50, "height": 100 } - }, - "323a8c42-404f-11e5-877d-e53327a933d0": { - "id": "323a8c42-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [44000, 15000], "end": [46000, 15000], "width": 50, "height": 100 } - }, - "323a8c43-404f-11e5-877d-e53327a933d0": { - "id": "323a8c43-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [44000, 16000], "end": [46000, 16000], "width": 50, "height": 100 } - }, - "323a8c44-404f-11e5-877d-e53327a933d0": { - "id": "323a8c44-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [39000, 22000], "end": [41000, 22000], "width": 50, "height": 100 } - }, - "323a8c45-404f-11e5-877d-e53327a933d0": { - "id": "323a8c45-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [41000, 33000], "end": [39000, 33000], "width": 50, "height": 100 } - }, - "323a8c46-404f-11e5-877d-e53327a933d0": { - "id": "323a8c46-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [41000, 32000], "end": [39000, 32000], "width": 50, "height": 100 } - }, - "323a8c47-404f-11e5-877d-e53327a933d0": { - "id": "323a8c47-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [41000, 31000], "end": [39000, 31000], "width": 50, "height": 100 } - }, - "323ab350-404f-11e5-877d-e53327a933d0": { - "id": "323ab350-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [41000, 30000], "end": [39000, 30000], "width": 50, "height": 100 } - }, - "323ab351-404f-11e5-877d-e53327a933d0": { - "id": "323ab351-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [29000, 33000], "end": [31000, 33000], "width": 50, "height": 100 } - }, - "323ab352-404f-11e5-877d-e53327a933d0": { - "id": "323ab352-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [44000, 30000], "end": [46000, 30000], "width": 50, "height": 100 } - }, - "323ab353-404f-11e5-877d-e53327a933d0": { - "id": "323ab353-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [44000, 31000], "end": [46000, 31000], "width": 50, "height": 100 } - }, - "323ab354-404f-11e5-877d-e53327a933d0": { - "id": "323ab354-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [44000, 32000], "end": [46000, 32000], "width": 50, "height": 100 } - }, - "323ab355-404f-11e5-877d-e53327a933d0": { - "id": "323ab355-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [44000, 33000], "end": [46000, 33000], "width": 50, "height": 100 } - }, - "323ab356-404f-11e5-877d-e53327a933d0": { - "id": "323ab356-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [39000, 23000], "end": [41000, 23000], "width": 50, "height": 100 } - }, - "323ab357-404f-11e5-877d-e53327a933d0": { - "id": "323ab357-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [39000, 25000], "end": [41000, 25000], "width": 50, "height": 100 } - }, - "323ab358-404f-11e5-877d-e53327a933d0": { - "id": "323ab358-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [39000, 26000], "end": [41000, 26000], "width": 50, "height": 100 } - }, - "323ada60-404f-11e5-877d-e53327a933d0": { - "id": "323ada60-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [34000, 26000], "end": [36000, 26000], "width": 50, "height": 100 } - }, - "323ada61-404f-11e5-877d-e53327a933d0": { - "id": "323ada61-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [8000, 14000], "end": [8000, 16000], "width": 50, "height": 100 } - }, - "323ada62-404f-11e5-877d-e53327a933d0": { - "id": "323ada62-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [8000, 24000], "end": [8000, 26000], "width": 50, "height": 100 } - }, - "323ada63-404f-11e5-877d-e53327a933d0": { - "id": "323ada63-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [8000, 34000], "end": [8000, 36000], "width": 50, "height": 100 } - }, - "323ada64-404f-11e5-877d-e53327a933d0": { - "id": "323ada64-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [8000, 9000], "end": [8000, 14000], "width": 250, "height": 100 } - }, - "323ada65-404f-11e5-877d-e53327a933d0": { - "id": "323ada65-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [8000, 16000], "end": [8000, 24000], "width": 250, "height": 100 } - }, - "323ada66-404f-11e5-877d-e53327a933d0": { - "id": "323ada66-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [8000, 26000], "end": [8000, 34000], "width": 250, "height": 100 } - }, - "323ada67-404f-11e5-877d-e53327a933d0": { - "id": "323ada67-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [8000, 36000], "end": [8000, 43000], "width": 250, "height": 100 } - }, - "323b0170-404f-11e5-877d-e53327a933d0": { - "id": "323b0170-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [11000, 28500], "end": [11000, 29100], "width": 250, "height": 100 } - }, - "323b0171-404f-11e5-877d-e53327a933d0": { - "id": "323b0171-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [11000, 29000], "end": [11000, 37000], "width": 250, "height": 100 } - }, - "323b0172-404f-11e5-877d-e53327a933d0": { - "id": "323b0172-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [11000, 26600], "end": [11000, 25900], "width": 250, "height": 100 } - }, - "323b0173-404f-11e5-877d-e53327a933d0": { - "id": "323b0173-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [11000, 26000], "end": [11000, 17000], "width": 250, "height": 100 } - }, - "323b0174-404f-11e5-877d-e53327a933d0": { - "id": "323b0174-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [9000, 9000], "end": [9000, 2000], "width": 250, "height": 100 } - }, - "323b0175-404f-11e5-877d-e53327a933d0": { - "id": "323b0175-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [9000, 11000], "end": [9000, 19000], "width": 250, "height": 100 } - }, - "323b2880-404f-11e5-877d-e53327a933d0": { - "id": "323b2880-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [9000, 21000], "end": [9000, 29000], "width": 250, "height": 100 } - }, - "323b2881-404f-11e5-877d-e53327a933d0": { - "id": "323b2881-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [9000, 31000], "end": [9000, 36000], "width": 250, "height": 100 } - }, - "323b2882-404f-11e5-877d-e53327a933d0": { - "id": "323b2882-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [11000, 17000], "end": [11000, 16500], "width": 250, "height": 100 } - }, - "323b2883-404f-11e5-877d-e53327a933d0": { - "id": "323b2883-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [12000, 16500], "end": [12000, 16000], "width": 250, "height": 100 } - }, - "323b2884-404f-11e5-877d-e53327a933d0": { - "id": "323b2884-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [12000, 16000], "end": [12000, 10000], "width": 250, "height": 100 } - }, - "323b4f90-404f-11e5-877d-e53327a933d0": { - "id": "323b4f90-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [12000, 18500], "end": [12000, 20000], "width": 250, "height": 100 } - }, - "323b4f91-404f-11e5-877d-e53327a933d0": { - "id": "323b4f91-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [12000, 20000], "end": [12000, 28000], "width": 250, "height": 100 } - }, - "323b4f92-404f-11e5-877d-e53327a933d0": { - "id": "323b4f92-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [12000, 28000], "end": [12000, 28500], "width": 250, "height": 100 } - }, - "323b4f93-404f-11e5-877d-e53327a933d0": { - "id": "323b4f93-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [14000, 31500], "end": [14000, 33500], "width": 250, "height": 100 } - }, - "323b4f94-404f-11e5-877d-e53327a933d0": { - "id": "323b4f94-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [14000, 13500], "end": [14000, 11500], "width": 250, "height": 100 } - }, - "323b4f95-404f-11e5-877d-e53327a933d0": { - "id": "323b4f95-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [14000, 11500], "end": [14000, 11000], "width": 250, "height": 100 } - }, - "323b4f96-404f-11e5-877d-e53327a933d0": { - "id": "323b4f96-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [9000, 2000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "323b4f97-404f-11e5-877d-e53327a933d0": { - "id": "323b4f97-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [23000, 12000], "end": [23000, 4000], "width": 250, "height": 100 } - }, - "323b4f98-404f-11e5-877d-e53327a933d0": { - "id": "323b4f98-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [23000, 4000], "end": [23000, 2000], "width": 250, "height": 100 } - }, - "323b4f99-404f-11e5-877d-e53327a933d0": { - "id": "323b4f99-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [24000, 23500], "end": [24000, 21000], "width": 250, "height": 100 } - }, - "323b76a0-404f-11e5-877d-e53327a933d0": { - "id": "323b76a0-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [24000, 12000], "end": [24000, 21000], "width": 250, "height": 100 } - }, - "323b76a1-404f-11e5-877d-e53327a933d0": { - "id": "323b76a1-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [12000, 10000], "end": [12000, 3000], "width": 250, "height": 100 } - }, - "323b76a2-404f-11e5-877d-e53327a933d0": { - "id": "323b76a2-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [12000, 3000], "end": [14000, 3000], "width": 250, "height": 100 } - }, - "323b76a3-404f-11e5-877d-e53327a933d0": { - "id": "323b76a3-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [14000, 3000], "end": [14000, 2000], "width": 250, "height": 100 } - }, - "323b76a4-404f-11e5-877d-e53327a933d0": { - "id": "323b76a4-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [14000, 11000], "end": [14000, 5000], "width": 250, "height": 100 } - }, - "323b9db0-404f-11e5-877d-e53327a933d0": { - "id": "323b9db0-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [14000, 5000], "end": [17000, 5000], "width": 250, "height": 100 } - }, - "323b9db1-404f-11e5-877d-e53327a933d0": { - "id": "323b9db1-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [17000, 5000], "end": [17000, 2000], "width": 250, "height": 100 } - }, - "323b9db2-404f-11e5-877d-e53327a933d0": { - "id": "323b9db2-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [11000, 37000], "end": [11000, 43000], "width": 250, "height": 100 } - }, - "323b9db3-404f-11e5-877d-e53327a933d0": { - "id": "323b9db3-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [11000, 43000], "end": [13000, 43000], "width": 250, "height": 100 } - }, - "323b9db4-404f-11e5-877d-e53327a933d0": { - "id": "323b9db4-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [8000, 43000], "end": [8000, 44000], "width": 250, "height": 100 } - }, - "323b9db5-404f-11e5-877d-e53327a933d0": { - "id": "323b9db5-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [13000, 43000], "end": [13000, 44000], "width": 250, "height": 100 } - }, - "323b9db6-404f-11e5-877d-e53327a933d0": { - "id": "323b9db6-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [14000, 33500], "end": [14000, 34000], "width": 250, "height": 100 } - }, - "323b9db7-404f-11e5-877d-e53327a933d0": { - "id": "323b9db7-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [14000, 34000], "end": [14000, 41000], "width": 250, "height": 100 } - }, - "323b9db8-404f-11e5-877d-e53327a933d0": { - "id": "323b9db8-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [14000, 41000], "end": [16000, 41000], "width": 250, "height": 100 } - }, - "323b9db9-404f-11e5-877d-e53327a933d0": { - "id": "323b9db9-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [16000, 41000], "end": [16000, 44000], "width": 250, "height": 100 } - }, - "323bc4c0-404f-11e5-877d-e53327a933d0": { - "id": "323bc4c0-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [14000, 2000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "323bc4c1-404f-11e5-877d-e53327a933d0": { - "id": "323bc4c1-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [17000, 2000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "323bc4c2-404f-11e5-877d-e53327a933d0": { - "id": "323bc4c2-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [16000, 44000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "323bc4c3-404f-11e5-877d-e53327a933d0": { - "id": "323bc4c3-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [13000, 44000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "323bc4c4-404f-11e5-877d-e53327a933d0": { - "id": "323bc4c4-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [8000, 44000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "323bc4c5-404f-11e5-877d-e53327a933d0": { - "id": "323bc4c5-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [23000, 2000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "323bc4c6-404f-11e5-877d-e53327a933d0": { - "id": "323bc4c6-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [24000, 10000], "end": [24000, 4000], "width": 250, "height": 100 } - }, - "323bc4c7-404f-11e5-877d-e53327a933d0": { - "id": "323bc4c7-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [24000, 4000], "end": [26000, 4000], "width": 250, "height": 100 } - }, - "323bc4c8-404f-11e5-877d-e53327a933d0": { - "id": "323bc4c8-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [26000, 4000], "end": [26000, 2000], "width": 250, "height": 100 } - }, - "323bebd0-404f-11e5-877d-e53327a933d0": { - "id": "323bebd0-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [23000, 33000], "end": [23000, 44000], "width": 250, "height": 100 } - }, - "323bebd1-404f-11e5-877d-e53327a933d0": { - "id": "323bebd1-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [23000, 44000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "323bebd2-404f-11e5-877d-e53327a933d0": { - "id": "323bebd2-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [26000, 2000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "323bebd3-404f-11e5-877d-e53327a933d0": { - "id": "323bebd3-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [28000, 18000], "end": [28000, 12000], "width": 250, "height": 100 } - }, - "323bebd4-404f-11e5-877d-e53327a933d0": { - "id": "323bebd4-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [28000, 12000], "end": [29000, 12000], "width": 250, "height": 100 } - }, - "323bebd5-404f-11e5-877d-e53327a933d0": { - "id": "323bebd5-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [31000, 12000], "end": [39000, 12000], "width": 250, "height": 100 } - }, - "323bebd6-404f-11e5-877d-e53327a933d0": { - "id": "323bebd6-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [29000, 13000], "end": [39000, 13000], "width": 250, "height": 100 } - }, - "323bebd7-404f-11e5-877d-e53327a933d0": { - "id": "323bebd7-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [33000, 18000], "end": [33000, 16000], "width": 250, "height": 100 } - }, - "323bebd8-404f-11e5-877d-e53327a933d0": { - "id": "323bebd8-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [37000, 18000], "end": [37000, 15000], "width": 250, "height": 100 } - }, - "323bebd9-404f-11e5-877d-e53327a933d0": { - "id": "323bebd9-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [33000, 16000], "end": [33000, 14000], "width": 250, "height": 100 } - }, - "323c12e0-404f-11e5-877d-e53327a933d0": { - "id": "323c12e0-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [33000, 14000], "end": [39000, 14000], "width": 250, "height": 100 } - }, - "323c12e1-404f-11e5-877d-e53327a933d0": { - "id": "323c12e1-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [37000, 15000], "end": [39000, 15000], "width": 250, "height": 100 } - }, - "323c12e2-404f-11e5-877d-e53327a933d0": { - "id": "323c12e2-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [39000, 16000], "end": [41000, 16000], "width": 250, "height": 100 } - }, - "323c12e3-404f-11e5-877d-e53327a933d0": { - "id": "323c12e3-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [29000, 19000], "end": [34000, 19000], "width": 250, "height": 100 } - }, - "323c12e4-404f-11e5-877d-e53327a933d0": { - "id": "323c12e4-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [36000, 19000], "end": [39000, 19000], "width": 250, "height": 100 } - }, - "323c12e5-404f-11e5-877d-e53327a933d0": { - "id": "323c12e5-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [34000, 20000], "end": [39000, 20000], "width": 250, "height": 100 } - }, - "323c12e6-404f-11e5-877d-e53327a933d0": { - "id": "323c12e6-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [41000, 19000], "end": [46000, 19000], "width": 250, "height": 100 } - }, - "323c12e7-404f-11e5-877d-e53327a933d0": { - "id": "323c12e7-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [41000, 20000], "end": [46000, 20000], "width": 250, "height": 100 } - }, - "323c12e8-404f-11e5-877d-e53327a933d0": { - "id": "323c12e8-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [41000, 22000], "end": [46000, 22000], "width": 250, "height": 100 } - }, - "323c12e9-404f-11e5-877d-e53327a933d0": { - "id": "323c12e9-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [41000, 23000], "end": [46000, 23000], "width": 250, "height": 100 } - }, - "323c39f0-404f-11e5-877d-e53327a933d0": { - "id": "323c39f0-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [41000, 25000], "end": [46000, 25000], "width": 250, "height": 100 } - }, - "323c39f1-404f-11e5-877d-e53327a933d0": { - "id": "323c39f1-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [41000, 26000], "end": [46000, 26000], "width": 250, "height": 100 } - }, - "323c39f2-404f-11e5-877d-e53327a933d0": { - "id": "323c39f2-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [41000, 30000], "end": [44000, 30000], "width": 250, "height": 100 } - }, - "323c39f3-404f-11e5-877d-e53327a933d0": { - "id": "323c39f3-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [41000, 31000], "end": [44000, 31000], "width": 250, "height": 100 } - }, - "323c39f4-404f-11e5-877d-e53327a933d0": { - "id": "323c39f4-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [41000, 32000], "end": [44000, 32000], "width": 250, "height": 100 } - }, - "323c39f5-404f-11e5-877d-e53327a933d0": { - "id": "323c39f5-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [41000, 33000], "end": [44000, 33000], "width": 250, "height": 100 } - }, - "323c39f6-404f-11e5-877d-e53327a933d0": { - "id": "323c39f6-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [31000, 33000], "end": [39000, 33000], "width": 250, "height": 100 } - }, - "323c39f7-404f-11e5-877d-e53327a933d0": { - "id": "323c39f7-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [29000, 32000], "end": [39000, 32000], "width": 250, "height": 100 } - }, - "323c39f8-404f-11e5-877d-e53327a933d0": { - "id": "323c39f8-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [33000, 27000], "end": [33000, 31000], "width": 250, "height": 100 } - }, - "323c6100-404f-11e5-877d-e53327a933d0": { - "id": "323c6100-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [33000, 31000], "end": [39000, 31000], "width": 250, "height": 100 } - }, - "323c6101-404f-11e5-877d-e53327a933d0": { - "id": "323c6101-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [36000, 27000], "end": [36000, 30000], "width": 250, "height": 100 } - }, - "323c6102-404f-11e5-877d-e53327a933d0": { - "id": "323c6102-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [36000, 30000], "end": [36000, 30000], "width": 250, "height": 100 } - }, - "323c6103-404f-11e5-877d-e53327a933d0": { - "id": "323c6103-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [36000, 30000], "end": [39000, 30000], "width": 250, "height": 100 } - }, - "323c6104-404f-11e5-877d-e53327a933d0": { - "id": "323c6104-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [36000, 26000], "end": [39000, 26000], "width": 250, "height": 100 } - }, - "323c6105-404f-11e5-877d-e53327a933d0": { - "id": "323c6105-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [39000, 25000], "end": [34000, 25000], "width": 250, "height": 100 } - }, - "323c6106-404f-11e5-877d-e53327a933d0": { - "id": "323c6106-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [39000, 22000], "end": [38000, 22000], "width": 250, "height": 100 } - }, - "323c6107-404f-11e5-877d-e53327a933d0": { - "id": "323c6107-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [34000, 21000], "end": [33000, 21000], "width": 250, "height": 100 } - }, - "323c6108-404f-11e5-877d-e53327a933d0": { - "id": "323c6108-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [33000, 21000], "end": [33000, 23000], "width": 250, "height": 100 } - }, - "323c6109-404f-11e5-877d-e53327a933d0": { - "id": "323c6109-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [33000, 23100], "end": [33000, 23500], "width": 250, "height": 100 } - }, - "323c8810-404f-11e5-877d-e53327a933d0": { - "id": "323c8810-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [38000, 22000], "end": [38000, 21000], "width": 250, "height": 100 } - }, - "323c8811-404f-11e5-877d-e53327a933d0": { - "id": "323c8811-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [38000, 21000], "end": [36000, 21000], "width": 250, "height": 100 } - }, - "323c8812-404f-11e5-877d-e53327a933d0": { - "id": "323c8812-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [36000, 22000], "end": [36000, 24000], "width": 250, "height": 100 } - }, - "323c8813-404f-11e5-877d-e53327a933d0": { - "id": "323c8813-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [36000, 24000], "end": [38000, 24000], "width": 250, "height": 100 } - }, - "323c8814-404f-11e5-877d-e53327a933d0": { - "id": "323c8814-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [38000, 24000], "end": [38000, 23000], "width": 250, "height": 100 } - }, - "323c8815-404f-11e5-877d-e53327a933d0": { - "id": "323c8815-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [38000, 23000], "end": [39000, 23000], "width": 250, "height": 100 } - }, - "323c8816-404f-11e5-877d-e53327a933d0": { - "id": "323c8816-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [29000, 26000], "end": [34000, 26000], "width": 250, "height": 100 } - }, - "323c8817-404f-11e5-877d-e53327a933d0": { - "id": "323c8817-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [29000, 33000], "end": [28000, 33000], "width": 250, "height": 100 } - }, - "323c8818-404f-11e5-877d-e53327a933d0": { - "id": "323c8818-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [28000, 33000], "end": [28000, 27000], "width": 250, "height": 100 } - }, - "323caf20-404f-11e5-877d-e53327a933d0": { - "id": "323caf20-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [46000, 12000], "end": [46000, 2000], "width": 250, "height": 100 } - }, - "323caf21-404f-11e5-877d-e53327a933d0": { - "id": "323caf21-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [46000, 13000], "end": [49000, 13000], "width": 250, "height": 100 } - }, - "323caf22-404f-11e5-877d-e53327a933d0": { - "id": "323caf22-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [49000, 13000], "end": [49000, 2000], "width": 250, "height": 100 } - }, - "323caf23-404f-11e5-877d-e53327a933d0": { - "id": "323caf23-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [46000, 14000], "end": [52000, 14000], "width": 250, "height": 100 } - }, - "323caf24-404f-11e5-877d-e53327a933d0": { - "id": "323caf24-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [52000, 14000], "end": [52000, 2000], "width": 250, "height": 100 } - }, - "323cd630-404f-11e5-877d-e53327a933d0": { - "id": "323cd630-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [46000, 15000], "end": [55000, 15000], "width": 250, "height": 100 } - }, - "323cfd40-404f-11e5-877d-e53327a933d0": { - "id": "323cfd40-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [55000, 15000], "end": [55000, 2000], "width": 250, "height": 100 } - }, - "323cfd41-404f-11e5-877d-e53327a933d0": { - "id": "323cfd41-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [46000, 16000], "end": [58000, 16000], "width": 250, "height": 100 } - }, - "323cfd42-404f-11e5-877d-e53327a933d0": { - "id": "323cfd42-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [58000, 16000], "end": [58000, 2000], "width": 250, "height": 100 } - }, - "323cfd43-404f-11e5-877d-e53327a933d0": { - "id": "323cfd43-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [46000, 33000], "end": [46000, 44000], "width": 250, "height": 100 } - }, - "323cfd44-404f-11e5-877d-e53327a933d0": { - "id": "323cfd44-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [46000, 32000], "end": [49000, 32000], "width": 250, "height": 100 } - }, - "323cfd45-404f-11e5-877d-e53327a933d0": { - "id": "323cfd45-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [49000, 32000], "end": [49000, 44000], "width": 250, "height": 100 } - }, - "323cfd46-404f-11e5-877d-e53327a933d0": { - "id": "323cfd46-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [46000, 31000], "end": [52000, 31000], "width": 250, "height": 100 } - }, - "323cfd47-404f-11e5-877d-e53327a933d0": { - "id": "323cfd47-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [52000, 31000], "end": [52000, 44000], "width": 250, "height": 100 } - }, - "323cfd48-404f-11e5-877d-e53327a933d0": { - "id": "323cfd48-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [46000, 30000], "end": [55000, 30000], "width": 250, "height": 100 } - }, - "323cfd49-404f-11e5-877d-e53327a933d0": { - "id": "323cfd49-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [55000, 30000], "end": [55000, 44000], "width": 250, "height": 100 } - }, - "323d2450-404f-11e5-877d-e53327a933d0": { - "id": "323d2450-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [46000, 19000], "end": [61000, 19000], "width": 250, "height": 100 } - }, - "323d2451-404f-11e5-877d-e53327a933d0": { - "id": "323d2451-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [46000, 20000], "end": [62000, 20000], "width": 250, "height": 100 } - }, - "323d2452-404f-11e5-877d-e53327a933d0": { - "id": "323d2452-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [44000, 12000], "end": [41000, 12000], "width": 250, "height": 100 } - }, - "323d2453-404f-11e5-877d-e53327a933d0": { - "id": "323d2453-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [44000, 13000], "end": [41000, 13000], "width": 250, "height": 100 } - }, - "323d2454-404f-11e5-877d-e53327a933d0": { - "id": "323d2454-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [44000, 14000], "end": [41000, 14000], "width": 250, "height": 100 } - }, - "323d2455-404f-11e5-877d-e53327a933d0": { - "id": "323d2455-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [41000, 15000], "end": [44000, 15000], "width": 250, "height": 100 } - }, - "323d2456-404f-11e5-877d-e53327a933d0": { - "id": "323d2456-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [41000, 16000], "end": [44000, 16000], "width": 250, "height": 100 } - }, - "323d2457-404f-11e5-877d-e53327a933d0": { - "id": "323d2457-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [42000, 16500], "end": [42000, 17600], "width": 250, "height": 100 } - }, - "323d4b60-404f-11e5-877d-e53327a933d0": { - "id": "323d4b60-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [42000, 17600], "end": [42000, 18000], "width": 250, "height": 100 } - }, - "323d4b61-404f-11e5-877d-e53327a933d0": { - "id": "323d4b61-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [42000, 18000], "end": [60000, 18000], "width": 250, "height": 100 } - }, - "323d4b62-404f-11e5-877d-e53327a933d0": { - "id": "323d4b62-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [60000, 18000], "end": [60000, 5000], "width": 250, "height": 100 } - }, - "323d4b63-404f-11e5-877d-e53327a933d0": { - "id": "323d4b63-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [60000, 5000], "end": [70000, 5000], "width": 250, "height": 100 } - }, - "323d4b64-404f-11e5-877d-e53327a933d0": { - "id": "323d4b64-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [61000, 19000], "end": [61000, 8000], "width": 250, "height": 100 } - }, - "323d4b65-404f-11e5-877d-e53327a933d0": { - "id": "323d4b65-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [61000, 8000], "end": [70000, 8000], "width": 250, "height": 100 } - }, - "323d4b66-404f-11e5-877d-e53327a933d0": { - "id": "323d4b66-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [62000, 20000], "end": [62000, 11000], "width": 250, "height": 100 } - }, - "323d4b67-404f-11e5-877d-e53327a933d0": { - "id": "323d4b67-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [62000, 11000], "end": [70000, 11000], "width": 250, "height": 100 } - }, - "323d4b68-404f-11e5-877d-e53327a933d0": { - "id": "323d4b68-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [46000, 22000], "end": [63000, 22000], "width": 250, "height": 100 } - }, - "323d7270-404f-11e5-877d-e53327a933d0": { - "id": "323d7270-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [63000, 22000], "end": [63000, 14000], "width": 250, "height": 100 } - }, - "323d7271-404f-11e5-877d-e53327a933d0": { - "id": "323d7271-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [63000, 14000], "end": [70000, 14000], "width": 250, "height": 100 } - }, - "323d7272-404f-11e5-877d-e53327a933d0": { - "id": "323d7272-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [46000, 23000], "end": [63000, 23000], "width": 250, "height": 100 } - }, - "323d7273-404f-11e5-877d-e53327a933d0": { - "id": "323d7273-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [42000, 27500], "end": [42000, 27100], "width": 250, "height": 100 } - }, - "323d7274-404f-11e5-877d-e53327a933d0": { - "id": "323d7274-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [42000, 27100], "end": [42000, 27000], "width": 250, "height": 100 } - }, - "323d7275-404f-11e5-877d-e53327a933d0": { - "id": "323d7275-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [46000, 25000], "end": [60000, 25000], "width": 250, "height": 100 } - }, - "323d7276-404f-11e5-877d-e53327a933d0": { - "id": "323d7276-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [42000, 27000], "end": [60000, 27000], "width": 250, "height": 100 } - }, - "323d9980-404f-11e5-877d-e53327a933d0": { - "id": "323d9980-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [39000, 29000], "end": [41000, 29000], "width": 250, "height": 100 } - }, - "323d9981-404f-11e5-877d-e53327a933d0": { - "id": "323d9981-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [41000, 29000], "end": [46000, 29000], "width": 250, "height": 100 } - }, - "323d9982-404f-11e5-877d-e53327a933d0": { - "id": "323d9982-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [42000, 27500], "end": [42000, 28500], "width": 250, "height": 100 } - }, - "323d9983-404f-11e5-877d-e53327a933d0": { - "id": "323d9983-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [46000, 26000], "end": [60000, 26000], "width": 250, "height": 100 } - }, - "323d9984-404f-11e5-877d-e53327a933d0": { - "id": "323d9984-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [46000, 29000], "end": [58000, 29000], "width": 250, "height": 100 } - }, - "323d9985-404f-11e5-877d-e53327a933d0": { - "id": "323d9985-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [58000, 29000], "end": [58000, 44000], "width": 250, "height": 100 } - }, - "323d9986-404f-11e5-877d-e53327a933d0": { - "id": "323d9986-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [60000, 27000], "end": [60000, 41000], "width": 250, "height": 100 } - }, - "323d9987-404f-11e5-877d-e53327a933d0": { - "id": "323d9987-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [60000, 41000], "end": [70000, 41000], "width": 250, "height": 100 } - }, - "323dc090-404f-11e5-877d-e53327a933d0": { - "id": "323dc090-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [60000, 26000], "end": [61000, 26000], "width": 250, "height": 100 } - }, - "323dc091-404f-11e5-877d-e53327a933d0": { - "id": "323dc091-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [61000, 26000], "end": [61000, 38000], "width": 250, "height": 100 } - }, - "323dc092-404f-11e5-877d-e53327a933d0": { - "id": "323dc092-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [61000, 38000], "end": [70000, 38000], "width": 250, "height": 100 } - }, - "323dc093-404f-11e5-877d-e53327a933d0": { - "id": "323dc093-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [60000, 25000], "end": [62000, 25000], "width": 250, "height": 100 } - }, - "323dc094-404f-11e5-877d-e53327a933d0": { - "id": "323dc094-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [62000, 25000], "end": [62000, 35000], "width": 250, "height": 100 } - }, - "323dc095-404f-11e5-877d-e53327a933d0": { - "id": "323dc095-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [62000, 35000], "end": [70000, 35000], "width": 250, "height": 100 } - }, - "323de7a0-404f-11e5-877d-e53327a933d0": { - "id": "323de7a0-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [63000, 23000], "end": [63000, 32000], "width": 250, "height": 100 } - }, - "323de7a1-404f-11e5-877d-e53327a933d0": { - "id": "323de7a1-404f-11e5-877d-e53327a933d0", - "name": "New Channel", - "type": "Channel", - "params": { "start": [63000, 32000], "end": [70000, 32000], "width": 250, "height": 100 } - }, - "323de7a2-404f-11e5-877d-e53327a933d0": { - "id": "323de7a2-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [46000, 2000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "323de7a3-404f-11e5-877d-e53327a933d0": { - "id": "323de7a3-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [49000, 2000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "323de7a4-404f-11e5-877d-e53327a933d0": { - "id": "323de7a4-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [52000, 2000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "323de7a5-404f-11e5-877d-e53327a933d0": { - "id": "323de7a5-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [55000, 2000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "323e0eb0-404f-11e5-877d-e53327a933d0": { - "id": "323e0eb0-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [58000, 2000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "323e0eb1-404f-11e5-877d-e53327a933d0": { - "id": "323e0eb1-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [70000, 5000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "323e0eb2-404f-11e5-877d-e53327a933d0": { - "id": "323e0eb2-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [70000, 8000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "323e0eb3-404f-11e5-877d-e53327a933d0": { - "id": "323e0eb3-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [70000, 11000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "323e0eb4-404f-11e5-877d-e53327a933d0": { - "id": "323e0eb4-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [70000, 14000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "323e0eb5-404f-11e5-877d-e53327a933d0": { - "id": "323e0eb5-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [70000, 32000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "323e0eb6-404f-11e5-877d-e53327a933d0": { - "id": "323e0eb6-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [70000, 35000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "323e0eb7-404f-11e5-877d-e53327a933d0": { - "id": "323e0eb7-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [70000, 38000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "323e35c0-404f-11e5-877d-e53327a933d0": { - "id": "323e35c0-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [70000, 41000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "323e35c1-404f-11e5-877d-e53327a933d0": { - "id": "323e35c1-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [58000, 44000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "323e35c2-404f-11e5-877d-e53327a933d0": { - "id": "323e35c2-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [55000, 44000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "323e35c3-404f-11e5-877d-e53327a933d0": { - "id": "323e35c3-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [52000, 44000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "323e35c4-404f-11e5-877d-e53327a933d0": { - "id": "323e35c4-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [49000, 44000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "323e35c5-404f-11e5-877d-e53327a933d0": { - "id": "323e35c5-404f-11e5-877d-e53327a933d0", - "name": "New Port", - "type": "Port", - "params": { "position": [46000, 44000], "radius1": 700, "radius2": 700, "height": 100 } - }, - "323e35c6-404f-11e5-877d-e53327a933d0": { - "id": "323e35c6-404f-11e5-877d-e53327a933d0", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [8900, 4000], "end": [9100, 6000], "borderWidth": 410, "height": 100 } - }, - "323e35c7-404f-11e5-877d-e53327a933d0": { - "id": "323e35c7-404f-11e5-877d-e53327a933d0", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [7900, 9000], "end": [8100, 11000], "borderWidth": 410, "height": 100 } - }, - "323e35c8-404f-11e5-877d-e53327a933d0": { - "id": "323e35c8-404f-11e5-877d-e53327a933d0", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [8900, 14000], "end": [9100, 16000], "borderWidth": 410, "height": 100 } - }, - "323e5cd0-404f-11e5-877d-e53327a933d0": { - "id": "323e5cd0-404f-11e5-877d-e53327a933d0", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [7900, 19000], "end": [8100, 21000], "borderWidth": 410, "height": 100 } - }, - "323e5cd1-404f-11e5-877d-e53327a933d0": { - "id": "323e5cd1-404f-11e5-877d-e53327a933d0", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [8900, 24000], "end": [9100, 26000], "borderWidth": 410, "height": 100 } - }, - "323e5cd2-404f-11e5-877d-e53327a933d0": { - "id": "323e5cd2-404f-11e5-877d-e53327a933d0", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [7900, 29000], "end": [8100, 31000], "borderWidth": 410, "height": 100 } - }, - "323e5cd3-404f-11e5-877d-e53327a933d0": { - "id": "323e5cd3-404f-11e5-877d-e53327a933d0", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [8900, 34000], "end": [9100, 36000], "borderWidth": 410, "height": 100 } - }, - "323e5cd4-404f-11e5-877d-e53327a933d0": { - "id": "323e5cd4-404f-11e5-877d-e53327a933d0", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [7900, 39000], "end": [8100, 40900], "borderWidth": 410, "height": 100 } - }, - "323e5cd5-404f-11e5-877d-e53327a933d0": { - "id": "323e5cd5-404f-11e5-877d-e53327a933d0", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [10900, 36500], "end": [11100, 38500], "borderWidth": 410, "height": 100 } - }, - "323e5cd6-404f-11e5-877d-e53327a933d0": { - "id": "323e5cd6-404f-11e5-877d-e53327a933d0", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [13900, 31500], "end": [14100, 33400], "borderWidth": 410, "height": 100 } - }, - "323e5cd7-404f-11e5-877d-e53327a933d0": { - "id": "323e5cd7-404f-11e5-877d-e53327a933d0", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [22900, 33000], "end": [23100, 35000], "borderWidth": 410, "height": 100 } - }, - "323e83e0-404f-11e5-877d-e53327a933d0": { - "id": "323e83e0-404f-11e5-877d-e53327a933d0", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [11900, 26500], "end": [12100, 28500], "borderWidth": 410, "height": 100 } - }, - "323e83e1-404f-11e5-877d-e53327a933d0": { - "id": "323e83e1-404f-11e5-877d-e53327a933d0", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [10900, 16500], "end": [11100, 18400], "borderWidth": 410, "height": 100 } - }, - "323e83e2-404f-11e5-877d-e53327a933d0": { - "id": "323e83e2-404f-11e5-877d-e53327a933d0", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [13900, 11600], "end": [14100, 13600], "borderWidth": 410, "height": 100 } - }, - "323e83e3-404f-11e5-877d-e53327a933d0": { - "id": "323e83e3-404f-11e5-877d-e53327a933d0", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [11900, 6500], "end": [12100, 8500], "borderWidth": 410, "height": 100 } - }, - "323e83e4-404f-11e5-877d-e53327a933d0": { - "id": "323e83e4-404f-11e5-877d-e53327a933d0", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [23900, 21500], "end": [24100, 23600], "borderWidth": 410, "height": 100 } - }, - "323e83e5-404f-11e5-877d-e53327a933d0": { - "id": "323e83e5-404f-11e5-877d-e53327a933d0", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [27900, 27000], "end": [28100, 29000], "borderWidth": 410, "height": 100 } - }, - "323e83e6-404f-11e5-877d-e53327a933d0": { - "id": "323e83e6-404f-11e5-877d-e53327a933d0", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [29000, 32100], "end": [31000, 31900], "borderWidth": 410, "height": 100 } - }, - "323e83e7-404f-11e5-877d-e53327a933d0": { - "id": "323e83e7-404f-11e5-877d-e53327a933d0", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [39000, 29100], "end": [41000, 28900], "borderWidth": 410, "height": 100 } - }, - "323e83e8-404f-11e5-877d-e53327a933d0": { - "id": "323e83e8-404f-11e5-877d-e53327a933d0", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [42100, 26900], "end": [41900, 28500], "borderWidth": 410, "height": 100 } - }, - "323e83e9-404f-11e5-877d-e53327a933d0": { - "id": "323e83e9-404f-11e5-877d-e53327a933d0", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [33900, 24900], "end": [36000, 25100], "borderWidth": 410, "height": 100 } - }, - "323eaaf0-404f-11e5-877d-e53327a933d0": { - "id": "323eaaf0-404f-11e5-877d-e53327a933d0", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [29000, 25900], "end": [31000, 26100], "borderWidth": 410, "height": 100 } - }, - "323eaaf1-404f-11e5-877d-e53327a933d0": { - "id": "323eaaf1-404f-11e5-877d-e53327a933d0", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [33100, 23500], "end": [32900, 21600], "borderWidth": 410, "height": 100 } - }, - "323eaaf2-404f-11e5-877d-e53327a933d0": { - "id": "323eaaf2-404f-11e5-877d-e53327a933d0", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [35900, 21600], "end": [36100, 23500], "borderWidth": 410, "height": 100 } - }, - "323eaaf3-404f-11e5-877d-e53327a933d0": { - "id": "323eaaf3-404f-11e5-877d-e53327a933d0", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [22900, 12000], "end": [23100, 10000], "borderWidth": 410, "height": 100 } - }, - "323eaaf4-404f-11e5-877d-e53327a933d0": { - "id": "323eaaf4-404f-11e5-877d-e53327a933d0", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [28100, 18000], "end": [27900, 16000], "borderWidth": 410, "height": 100 } - }, - "323eaaf5-404f-11e5-877d-e53327a933d0": { - "id": "323eaaf5-404f-11e5-877d-e53327a933d0", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [29000, 19100], "end": [31000, 18900], "borderWidth": 410, "height": 100 } - }, - "323eaaf6-404f-11e5-877d-e53327a933d0": { - "id": "323eaaf6-404f-11e5-877d-e53327a933d0", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [32900, 18000], "end": [33100, 16000], "borderWidth": 410, "height": 100 } - }, - "323eaaf7-404f-11e5-877d-e53327a933d0": { - "id": "323eaaf7-404f-11e5-877d-e53327a933d0", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [29000, 13100], "end": [31000, 12900], "borderWidth": 410, "height": 100 } - }, - "323eaaf8-404f-11e5-877d-e53327a933d0": { - "id": "323eaaf8-404f-11e5-877d-e53327a933d0", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [36900, 16000], "end": [37100, 18000], "borderWidth": 410, "height": 100 } - }, - "323ed200-404f-11e5-877d-e53327a933d0": { - "id": "323ed200-404f-11e5-877d-e53327a933d0", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [39000, 16100], "end": [41000, 15900], "borderWidth": 410, "height": 100 } - }, - "323ed201-404f-11e5-877d-e53327a933d0": { - "id": "323ed201-404f-11e5-877d-e53327a933d0", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [41900, 16500], "end": [42000, 18000], "borderWidth": 410, "height": 100 } - }, - "38159240-404f-11e5-877d-e53327a933d0": { - "id": "38159240-404f-11e5-877d-e53327a933d0", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [32900, 27000], "end": [33100, 29000], "borderWidth": 410, "height": 100 } - }, - "39f06cc0-404f-11e5-877d-e53327a933d0": { - "id": "39f06cc0-404f-11e5-877d-e53327a933d0", - "name": "New Chamber", - "type": "Chamber", - "params": { "start": [35900, 27000], "end": [36100, 29000], "borderWidth": 410, "height": 100 } - } - } - } - ], - "groups": [], - "defaults": {} -} diff --git a/dist/favicon.ico b/favicon.ico similarity index 100% rename from dist/favicon.ico rename to favicon.ico diff --git a/dist/fonts/Roboto-Black.313a6563.woff b/fonts/Roboto-Black.313a6563.woff similarity index 100% rename from dist/fonts/Roboto-Black.313a6563.woff rename to fonts/Roboto-Black.313a6563.woff diff --git a/dist/fonts/Roboto-Black.59eb3601.woff2 b/fonts/Roboto-Black.59eb3601.woff2 similarity index 100% rename from dist/fonts/Roboto-Black.59eb3601.woff2 rename to fonts/Roboto-Black.59eb3601.woff2 diff --git a/dist/fonts/Roboto-BlackItalic.cc2fadc3.woff b/fonts/Roboto-BlackItalic.cc2fadc3.woff similarity index 100% rename from dist/fonts/Roboto-BlackItalic.cc2fadc3.woff rename to fonts/Roboto-BlackItalic.cc2fadc3.woff diff --git a/dist/fonts/Roboto-BlackItalic.f75569f8.woff2 b/fonts/Roboto-BlackItalic.f75569f8.woff2 similarity index 100% rename from dist/fonts/Roboto-BlackItalic.f75569f8.woff2 rename to fonts/Roboto-BlackItalic.f75569f8.woff2 diff --git a/dist/fonts/Roboto-Bold.50d75e48.woff b/fonts/Roboto-Bold.50d75e48.woff similarity index 100% rename from dist/fonts/Roboto-Bold.50d75e48.woff rename to fonts/Roboto-Bold.50d75e48.woff diff --git a/dist/fonts/Roboto-Bold.b52fac2b.woff2 b/fonts/Roboto-Bold.b52fac2b.woff2 similarity index 100% rename from dist/fonts/Roboto-Bold.b52fac2b.woff2 rename to fonts/Roboto-Bold.b52fac2b.woff2 diff --git a/dist/fonts/Roboto-BoldItalic.4fe0f73c.woff b/fonts/Roboto-BoldItalic.4fe0f73c.woff similarity index 100% rename from dist/fonts/Roboto-BoldItalic.4fe0f73c.woff rename to fonts/Roboto-BoldItalic.4fe0f73c.woff diff --git a/dist/fonts/Roboto-BoldItalic.94008e69.woff2 b/fonts/Roboto-BoldItalic.94008e69.woff2 similarity index 100% rename from dist/fonts/Roboto-BoldItalic.94008e69.woff2 rename to fonts/Roboto-BoldItalic.94008e69.woff2 diff --git a/dist/fonts/Roboto-Light.c73eb1ce.woff b/fonts/Roboto-Light.c73eb1ce.woff similarity index 100% rename from dist/fonts/Roboto-Light.c73eb1ce.woff rename to fonts/Roboto-Light.c73eb1ce.woff diff --git a/dist/fonts/Roboto-Light.d26871e8.woff2 b/fonts/Roboto-Light.d26871e8.woff2 similarity index 100% rename from dist/fonts/Roboto-Light.d26871e8.woff2 rename to fonts/Roboto-Light.d26871e8.woff2 diff --git a/dist/fonts/Roboto-LightItalic.13efe6cb.woff b/fonts/Roboto-LightItalic.13efe6cb.woff similarity index 100% rename from dist/fonts/Roboto-LightItalic.13efe6cb.woff rename to fonts/Roboto-LightItalic.13efe6cb.woff diff --git a/dist/fonts/Roboto-LightItalic.e8eaae90.woff2 b/fonts/Roboto-LightItalic.e8eaae90.woff2 similarity index 100% rename from dist/fonts/Roboto-LightItalic.e8eaae90.woff2 rename to fonts/Roboto-LightItalic.e8eaae90.woff2 diff --git a/dist/fonts/Roboto-Medium.1d659482.woff b/fonts/Roboto-Medium.1d659482.woff similarity index 100% rename from dist/fonts/Roboto-Medium.1d659482.woff rename to fonts/Roboto-Medium.1d659482.woff diff --git a/dist/fonts/Roboto-Medium.90d16760.woff2 b/fonts/Roboto-Medium.90d16760.woff2 similarity index 100% rename from dist/fonts/Roboto-Medium.90d16760.woff2 rename to fonts/Roboto-Medium.90d16760.woff2 diff --git a/dist/fonts/Roboto-MediumItalic.13ec0eb5.woff2 b/fonts/Roboto-MediumItalic.13ec0eb5.woff2 similarity index 100% rename from dist/fonts/Roboto-MediumItalic.13ec0eb5.woff2 rename to fonts/Roboto-MediumItalic.13ec0eb5.woff2 diff --git a/dist/fonts/Roboto-MediumItalic.83e114c3.woff b/fonts/Roboto-MediumItalic.83e114c3.woff similarity index 100% rename from dist/fonts/Roboto-MediumItalic.83e114c3.woff rename to fonts/Roboto-MediumItalic.83e114c3.woff diff --git a/dist/fonts/Roboto-Regular.35b07eb2.woff b/fonts/Roboto-Regular.35b07eb2.woff similarity index 100% rename from dist/fonts/Roboto-Regular.35b07eb2.woff rename to fonts/Roboto-Regular.35b07eb2.woff diff --git a/dist/fonts/Roboto-Regular.73f0a88b.woff2 b/fonts/Roboto-Regular.73f0a88b.woff2 similarity index 100% rename from dist/fonts/Roboto-Regular.73f0a88b.woff2 rename to fonts/Roboto-Regular.73f0a88b.woff2 diff --git a/dist/fonts/Roboto-RegularItalic.4357beb8.woff2 b/fonts/Roboto-RegularItalic.4357beb8.woff2 similarity index 100% rename from dist/fonts/Roboto-RegularItalic.4357beb8.woff2 rename to fonts/Roboto-RegularItalic.4357beb8.woff2 diff --git a/dist/fonts/Roboto-RegularItalic.f5902d5e.woff b/fonts/Roboto-RegularItalic.f5902d5e.woff similarity index 100% rename from dist/fonts/Roboto-RegularItalic.f5902d5e.woff rename to fonts/Roboto-RegularItalic.f5902d5e.woff diff --git a/dist/fonts/Roboto-Thin.ad538a69.woff2 b/fonts/Roboto-Thin.ad538a69.woff2 similarity index 100% rename from dist/fonts/Roboto-Thin.ad538a69.woff2 rename to fonts/Roboto-Thin.ad538a69.woff2 diff --git a/dist/fonts/Roboto-Thin.d3b47375.woff b/fonts/Roboto-Thin.d3b47375.woff similarity index 100% rename from dist/fonts/Roboto-Thin.d3b47375.woff rename to fonts/Roboto-Thin.d3b47375.woff diff --git a/dist/fonts/Roboto-ThinItalic.5b4a33e1.woff2 b/fonts/Roboto-ThinItalic.5b4a33e1.woff2 similarity index 100% rename from dist/fonts/Roboto-ThinItalic.5b4a33e1.woff2 rename to fonts/Roboto-ThinItalic.5b4a33e1.woff2 diff --git a/dist/fonts/Roboto-ThinItalic.8a96edbb.woff b/fonts/Roboto-ThinItalic.8a96edbb.woff similarity index 100% rename from dist/fonts/Roboto-ThinItalic.8a96edbb.woff rename to fonts/Roboto-ThinItalic.8a96edbb.woff diff --git a/dist/fonts/materialdesignicons-webfont.147e3378.woff b/fonts/materialdesignicons-webfont.147e3378.woff similarity index 100% rename from dist/fonts/materialdesignicons-webfont.147e3378.woff rename to fonts/materialdesignicons-webfont.147e3378.woff diff --git a/dist/fonts/materialdesignicons-webfont.174c02fc.ttf b/fonts/materialdesignicons-webfont.174c02fc.ttf similarity index 100% rename from dist/fonts/materialdesignicons-webfont.174c02fc.ttf rename to fonts/materialdesignicons-webfont.174c02fc.ttf diff --git a/dist/fonts/materialdesignicons-webfont.64d4cf64.eot b/fonts/materialdesignicons-webfont.64d4cf64.eot similarity index 100% rename from dist/fonts/materialdesignicons-webfont.64d4cf64.eot rename to fonts/materialdesignicons-webfont.64d4cf64.eot diff --git a/dist/fonts/materialdesignicons-webfont.7a44ea19.woff2 b/fonts/materialdesignicons-webfont.7a44ea19.woff2 similarity index 100% rename from dist/fonts/materialdesignicons-webfont.7a44ea19.woff2 rename to fonts/materialdesignicons-webfont.7a44ea19.woff2 diff --git a/dist/img/3DuF_favicon_large.svg b/img/3DuF_favicon_large.svg similarity index 100% rename from dist/img/3DuF_favicon_large.svg rename to img/3DuF_favicon_large.svg diff --git a/dist/img/3DuF_placeholder_logo.png b/img/3DuF_placeholder_logo.png similarity index 100% rename from dist/img/3DuF_placeholder_logo.png rename to img/3DuF_placeholder_logo.png diff --git a/dist/img/3DuF_placeholder_png.png b/img/3DuF_placeholder_png.png similarity index 100% rename from dist/img/3DuF_placeholder_png.png rename to img/3DuF_placeholder_png.png diff --git a/dist/img/3DuF_placeholder_svg.svg b/img/3DuF_placeholder_svg.svg similarity index 100% rename from dist/img/3DuF_placeholder_svg.svg rename to img/3DuF_placeholder_svg.svg diff --git a/dist/img/CHANNEL.6ac8d4e3.png b/img/CHANNEL.6ac8d4e3.png similarity index 100% rename from dist/img/CHANNEL.6ac8d4e3.png rename to img/CHANNEL.6ac8d4e3.png diff --git a/dist/img/cidar_logo.png b/img/cidar_logo.png similarity index 100% rename from dist/img/cidar_logo.png rename to img/cidar_logo.png diff --git a/dist/img/favicon_large.png b/img/favicon_large.png similarity index 100% rename from dist/img/favicon_large.png rename to img/favicon_large.png diff --git a/dist/img/logo.png b/img/logo.png similarity index 100% rename from dist/img/logo.png rename to img/logo.png diff --git a/dist/index.html b/index.html similarity index 100% rename from dist/index.html rename to index.html diff --git a/dist/index2.html b/index2.html similarity index 100% rename from dist/index2.html rename to index2.html diff --git a/dist/js/app.5e0ea8c0.js b/js/app.5e0ea8c0.js similarity index 100% rename from dist/js/app.5e0ea8c0.js rename to js/app.5e0ea8c0.js diff --git a/dist/js/app.5e0ea8c0.js.map b/js/app.5e0ea8c0.js.map similarity index 100% rename from dist/js/app.5e0ea8c0.js.map rename to js/app.5e0ea8c0.js.map diff --git a/dist/js/chunk-vendors.68475a27.js b/js/chunk-vendors.68475a27.js similarity index 100% rename from dist/js/chunk-vendors.68475a27.js rename to js/chunk-vendors.68475a27.js diff --git a/dist/js/chunk-vendors.68475a27.js.map b/js/chunk-vendors.68475a27.js.map similarity index 100% rename from dist/js/chunk-vendors.68475a27.js.map rename to js/chunk-vendors.68475a27.js.map diff --git a/lib/bootstrap/bootstrap-theme.min.css b/lib/bootstrap/bootstrap-theme.min.css deleted file mode 100644 index 61358b13..00000000 --- a/lib/bootstrap/bootstrap-theme.min.css +++ /dev/null @@ -1,5 +0,0 @@ -/*! - * Bootstrap v3.3.5 (http://getbootstrap.com) - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */.btn-danger,.btn-default,.btn-info,.btn-primary,.btn-success,.btn-warning{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-danger.active,.btn-danger:active,.btn-default.active,.btn-default:active,.btn-info.active,.btn-info:active,.btn-primary.active,.btn-primary:active,.btn-success.active,.btn-success:active,.btn-warning.active,.btn-warning:active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-danger.disabled,.btn-danger[disabled],.btn-default.disabled,.btn-default[disabled],.btn-info.disabled,.btn-info[disabled],.btn-primary.disabled,.btn-primary[disabled],.btn-success.disabled,.btn-success[disabled],.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-danger,fieldset[disabled] .btn-default,fieldset[disabled] .btn-info,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-success,fieldset[disabled] .btn-warning{-webkit-box-shadow:none;box-shadow:none}.btn-danger .badge,.btn-default .badge,.btn-info .badge,.btn-primary .badge,.btn-success .badge,.btn-warning .badge{text-shadow:none}.btn.active,.btn:active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;border-color:#ccc}.btn-default:focus,.btn-default:hover{background-color:#e0e0e0;background-position:0 -15px}.btn-default.active,.btn-default:active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-o-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#265a88));background-image:linear-gradient(to bottom,#337ab7 0,#265a88 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#245580}.btn-primary:focus,.btn-primary:hover{background-color:#265a88;background-position:0 -15px}.btn-primary.active,.btn-primary:active{background-color:#265a88;border-color:#245580}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#265a88;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:focus,.btn-success:hover{background-color:#419641;background-position:0 -15px}.btn-success.active,.btn-success:active{background-color:#419641;border-color:#3e8f3e}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:focus,.btn-info:hover{background-color:#2aabd2;background-position:0 -15px}.btn-info.active,.btn-info:active{background-color:#2aabd2;border-color:#28a4c9}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:focus,.btn-warning:hover{background-color:#eb9316;background-position:0 -15px}.btn-warning.active,.btn-warning:active{background-color:#eb9316;border-color:#e38d13}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:focus,.btn-danger:hover{background-color:#c12e2a;background-position:0 -15px}.btn-danger.active,.btn-danger:active{background-color:#c12e2a;border-color:#b92c28}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#c12e2a;background-image:none}.img-thumbnail,.thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{background-color:#2e6da4;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-o-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dbdbdb),to(#e2e2e2));background-image:linear-gradient(to bottom,#dbdbdb 0,#e2e2e2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-o-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#080808),to(#0f0f0f));background-image:linear-gradient(to bottom,#080808 0,#0f0f0f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-fixed-bottom,.navbar-fixed-top,.navbar-static-top{border-radius:0}@media (max-width:767px){.navbar .navbar-nav .open .dropdown-menu>.active>a,.navbar .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-o-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#286090));background-image:linear-gradient(to bottom,#337ab7 0,#286090 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{text-shadow:0 -1px 0 #286090;background-image:-webkit-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2b669a));background-image:linear-gradient(to bottom,#337ab7 0,#2b669a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);background-repeat:repeat-x;border-color:#2b669a}.list-group-item.active .badge,.list-group-item.active:focus .badge,.list-group-item.active:hover .badge{text-shadow:none}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)} \ No newline at end of file diff --git a/lib/bootstrap/bootstrap.min.css b/lib/bootstrap/bootstrap.min.css deleted file mode 100644 index d65c66b1..00000000 --- a/lib/bootstrap/bootstrap.min.css +++ /dev/null @@ -1,5 +0,0 @@ -/*! - * Bootstrap v3.3.5 (http://getbootstrap.com) - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=checkbox]:focus,input[type=radio]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=time].form-control,input[type=datetime-local].form-control,input[type=month].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px\9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:14.33px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:3;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:2;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{min-height:16.43px;padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;filter:alpha(opacity=0);opacity:0;line-break:auto}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);line-break:auto}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-15px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-15px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-15px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}} \ No newline at end of file diff --git a/lib/bootstrap/bootstrap.min.js b/lib/bootstrap/bootstrap.min.js deleted file mode 100644 index 133aeecb..00000000 --- a/lib/bootstrap/bootstrap.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/*! - * Bootstrap v3.3.5 (http://getbootstrap.com) - * Copyright 2011-2015 Twitter, Inc. - * Licensed under the MIT license - */ -if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.5",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a(f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.5",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")?(c.prop("checked")&&(a=!1),b.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==c.prop("type")&&(c.prop("checked")!==this.$element.hasClass("active")&&(a=!1),this.$element.toggleClass("active")),c.prop("checked",this.$element.hasClass("active")),a&&c.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),a(c.target).is('input[type="radio"]')||a(c.target).is('input[type="checkbox"]')||c.preventDefault()}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.5",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));return a>this.$items.length-1||0>a?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide("next")},c.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.5",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function c(c){c&&3===c.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=b(d),f={relatedTarget:this};e.hasClass("open")&&(c&&"click"==c.type&&/input|textarea/i.test(c.target.tagName)&&a.contains(e[0],c.target)||(e.trigger(c=a.Event("hide.bs.dropdown",f)),c.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger("hidden.bs.dropdown",f))))}))}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.5",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=b(e),g=f.hasClass("open");if(c(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",c);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),f.toggleClass("open").trigger("shown.bs.dropdown",h)}return!1}},g.prototype.keydown=function(c){if(/(38|40|27|32)/.test(c.which)&&!/input|textarea/i.test(c.target.tagName)){var d=a(this);if(c.preventDefault(),c.stopPropagation(),!d.is(".disabled, :disabled")){var e=b(d),g=e.hasClass("open");if(!g&&27!=c.which||g&&27==c.which)return 27==c.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.disabled):visible a",i=e.find(".dropdown-menu"+h);if(i.length){var j=i.index(c.target);38==c.which&&j>0&&j--,40==c.which&&jdocument.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&a?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!a?this.scrollbarWidth:""})},c.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},c.prototype.checkScrollbar=function(){var a=window.innerWidth;if(!a){var b=document.documentElement.getBoundingClientRect();a=b.right-Math.abs(b.left)}this.bodyIsOverflowing=document.body.clientWidth
',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),c.isInStateTrue()?void 0:(clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide())},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-mo.width?"left":"left"==h&&k.left-lg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;(e||!/destroy|hide/.test(b))&&(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.5",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.5",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b=e[a]&&(void 0===e[a+1]||b .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.5",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return c>e?"top":!1;if("bottom"==this.affixed)return null!=c?e+this.unpin<=f.top?!1:"bottom":a-d>=e+g?!1:"bottom";var h=null==this.affixed,i=h?e:f.top,j=h?g:b;return null!=c&&c>=e?"top":null!=d&&i+j>=a-d?"bottom":!1},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); \ No newline at end of file diff --git a/lib/canvas_rendering/canvasrenderer.js b/lib/canvas_rendering/canvasrenderer.js deleted file mode 100644 index 2beb2601..00000000 --- a/lib/canvas_rendering/canvasrenderer.js +++ /dev/null @@ -1,1098 +0,0 @@ -/** - * @author mrdoob / http://mrdoob.com/ - */ - -THREE.SpriteCanvasMaterial = function ( parameters ) { - - THREE.Material.call( this ); - - this.type = 'SpriteCanvasMaterial'; - - this.color = new THREE.Color( 0xffffff ); - this.program = function ( context, color ) {}; - - this.setValues( parameters ); - -}; - -THREE.SpriteCanvasMaterial.prototype = Object.create( THREE.Material.prototype ); -THREE.SpriteCanvasMaterial.prototype.constructor = THREE.SpriteCanvasMaterial; - -THREE.SpriteCanvasMaterial.prototype.clone = function () { - - var material = new THREE.SpriteCanvasMaterial(); - - THREE.Material.prototype.clone.call( this, material ); - - material.color.copy( this.color ); - material.program = this.program; - - return material; - -}; - -// - -THREE.CanvasRenderer = function ( parameters ) { - - console.log( 'THREE.CanvasRenderer', THREE.REVISION ); - - var smoothstep = THREE.Math.smoothstep; - - parameters = parameters || {}; - - var _this = this, - _renderData, _elements, _lights, - _projector = new THREE.Projector(), - - _canvas = parameters.canvas !== undefined - ? parameters.canvas - : document.createElement( 'canvas' ), - - _canvasWidth = _canvas.width, - _canvasHeight = _canvas.height, - _canvasWidthHalf = Math.floor( _canvasWidth / 2 ), - _canvasHeightHalf = Math.floor( _canvasHeight / 2 ), - - _viewportX = 0, - _viewportY = 0, - _viewportWidth = _canvasWidth, - _viewportHeight = _canvasHeight, - - pixelRatio = 1, - - _context = _canvas.getContext( '2d', { - alpha: parameters.alpha === true - } ), - - _clearColor = new THREE.Color( 0x000000 ), - _clearAlpha = parameters.alpha === true ? 0 : 1, - - _contextGlobalAlpha = 1, - _contextGlobalCompositeOperation = 0, - _contextStrokeStyle = null, - _contextFillStyle = null, - _contextLineWidth = null, - _contextLineCap = null, - _contextLineJoin = null, - _contextLineDash = [], - - _camera, - - _v1, _v2, _v3, _v4, - _v5 = new THREE.RenderableVertex(), - _v6 = new THREE.RenderableVertex(), - - _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, - _v4x, _v4y, _v5x, _v5y, _v6x, _v6y, - - _color = new THREE.Color(), - _color1 = new THREE.Color(), - _color2 = new THREE.Color(), - _color3 = new THREE.Color(), - _color4 = new THREE.Color(), - - _diffuseColor = new THREE.Color(), - _emissiveColor = new THREE.Color(), - - _lightColor = new THREE.Color(), - - _patterns = {}, - - _image, _uvs, - _uv1x, _uv1y, _uv2x, _uv2y, _uv3x, _uv3y, - - _clipBox = new THREE.Box2(), - _clearBox = new THREE.Box2(), - _elemBox = new THREE.Box2(), - - _ambientLight = new THREE.Color(), - _directionalLights = new THREE.Color(), - _pointLights = new THREE.Color(), - - _vector3 = new THREE.Vector3(), // Needed for PointLight - _centroid = new THREE.Vector3(), - _normal = new THREE.Vector3(), - _normalViewMatrix = new THREE.Matrix3(); - - // dash+gap fallbacks for Firefox and everything else - - if ( _context.setLineDash === undefined ) { - - _context.setLineDash = function () {} - - } - - this.domElement = _canvas; - - this.autoClear = true; - this.sortObjects = true; - this.sortElements = true; - - this.info = { - - render: { - - vertices: 0, - faces: 0 - - } - - } - - // WebGLRenderer compatibility - - this.supportsVertexTextures = function () {}; - this.setFaceCulling = function () {}; - - // - - this.getPixelRatio = function () { - - return pixelRatio; - - }; - - this.setPixelRatio = function ( value ) { - - pixelRatio = value; - - }; - - this.setSize = function ( width, height, updateStyle ) { - - _canvasWidth = width * pixelRatio; - _canvasHeight = height * pixelRatio; - - _canvas.width = _canvasWidth; - _canvas.height = _canvasHeight; - - _canvasWidthHalf = Math.floor( _canvasWidth / 2 ); - _canvasHeightHalf = Math.floor( _canvasHeight / 2 ); - - if ( updateStyle !== false ) { - - _canvas.style.width = width + 'px'; - _canvas.style.height = height + 'px'; - - } - - _clipBox.min.set( -_canvasWidthHalf, -_canvasHeightHalf ), - _clipBox.max.set( _canvasWidthHalf, _canvasHeightHalf ); - - _clearBox.min.set( - _canvasWidthHalf, - _canvasHeightHalf ); - _clearBox.max.set( _canvasWidthHalf, _canvasHeightHalf ); - - _contextGlobalAlpha = 1; - _contextGlobalCompositeOperation = 0; - _contextStrokeStyle = null; - _contextFillStyle = null; - _contextLineWidth = null; - _contextLineCap = null; - _contextLineJoin = null; - - this.setViewport( 0, 0, width, height ); - - }; - - this.setViewport = function ( x, y, width, height ) { - - _viewportX = x * pixelRatio; - _viewportY = y * pixelRatio; - - _viewportWidth = width * pixelRatio; - _viewportHeight = height * pixelRatio; - - }; - - this.setScissor = function () {}; - this.enableScissorTest = function () {}; - - this.setClearColor = function ( color, alpha ) { - - _clearColor.set( color ); - _clearAlpha = alpha !== undefined ? alpha : 1; - - _clearBox.min.set( - _canvasWidthHalf, - _canvasHeightHalf ); - _clearBox.max.set( _canvasWidthHalf, _canvasHeightHalf ); - - }; - - this.setClearColorHex = function ( hex, alpha ) { - - console.warn( 'THREE.CanvasRenderer: .setClearColorHex() is being removed. Use .setClearColor() instead.' ); - this.setClearColor( hex, alpha ); - - }; - - this.getClearColor = function () { - - return _clearColor; - - }; - - this.getClearAlpha = function () { - - return _clearAlpha; - - }; - - this.getMaxAnisotropy = function () { - - return 0; - - }; - - this.clear = function () { - - if ( _clearBox.empty() === false ) { - - _clearBox.intersect( _clipBox ); - _clearBox.expandByScalar( 2 ); - - _clearBox.min.x = _clearBox.min.x + _canvasWidthHalf; - _clearBox.min.y = - _clearBox.min.y + _canvasHeightHalf; // higher y value ! - _clearBox.max.x = _clearBox.max.x + _canvasWidthHalf; - _clearBox.max.y = - _clearBox.max.y + _canvasHeightHalf; // lower y value ! - - if ( _clearAlpha < 1 ) { - - _context.clearRect( - _clearBox.min.x | 0, - _clearBox.max.y | 0, - ( _clearBox.max.x - _clearBox.min.x ) | 0, - ( _clearBox.min.y - _clearBox.max.y ) | 0 - ); - - } - - if ( _clearAlpha > 0 ) { - - setBlending( THREE.NormalBlending ); - setOpacity( 1 ); - - setFillStyle( 'rgba(' + Math.floor( _clearColor.r * 255 ) + ',' + Math.floor( _clearColor.g * 255 ) + ',' + Math.floor( _clearColor.b * 255 ) + ',' + _clearAlpha + ')' ); - - _context.fillRect( - _clearBox.min.x | 0, - _clearBox.max.y | 0, - ( _clearBox.max.x - _clearBox.min.x ) | 0, - ( _clearBox.min.y - _clearBox.max.y ) | 0 - ); - - } - - _clearBox.makeEmpty(); - - } - - }; - - // compatibility - - this.clearColor = function () {}; - this.clearDepth = function () {}; - this.clearStencil = function () {}; - - this.render = function ( scene, camera ) { - - if ( camera instanceof THREE.Camera === false ) { - - console.error( 'THREE.CanvasRenderer.render: camera is not an instance of THREE.Camera.' ); - return; - - } - - if ( this.autoClear === true ) this.clear(); - - _this.info.render.vertices = 0; - _this.info.render.faces = 0; - - _context.setTransform( _viewportWidth / _canvasWidth, 0, 0, - _viewportHeight / _canvasHeight, _viewportX, _canvasHeight - _viewportY ); - _context.translate( _canvasWidthHalf, _canvasHeightHalf ); - - _renderData = _projector.projectScene( scene, camera, this.sortObjects, this.sortElements ); - _elements = _renderData.elements; - _lights = _renderData.lights; - _camera = camera; - - _normalViewMatrix.getNormalMatrix( camera.matrixWorldInverse ); - - /* DEBUG - setFillStyle( 'rgba( 0, 255, 255, 0.5 )' ); - _context.fillRect( _clipBox.min.x, _clipBox.min.y, _clipBox.max.x - _clipBox.min.x, _clipBox.max.y - _clipBox.min.y ); - */ - - calculateLights(); - - for ( var e = 0, el = _elements.length; e < el; e ++ ) { - - var element = _elements[ e ]; - - var material = element.material; - - if ( material === undefined || material.opacity === 0 ) continue; - - _elemBox.makeEmpty(); - - if ( element instanceof THREE.RenderableSprite ) { - - _v1 = element; - _v1.x *= _canvasWidthHalf; _v1.y *= _canvasHeightHalf; - - renderSprite( _v1, element, material ); - - } else if ( element instanceof THREE.RenderableLine ) { - - _v1 = element.v1; _v2 = element.v2; - - _v1.positionScreen.x *= _canvasWidthHalf; _v1.positionScreen.y *= _canvasHeightHalf; - _v2.positionScreen.x *= _canvasWidthHalf; _v2.positionScreen.y *= _canvasHeightHalf; - - _elemBox.setFromPoints( [ - _v1.positionScreen, - _v2.positionScreen - ] ); - - if ( _clipBox.isIntersectionBox( _elemBox ) === true ) { - - renderLine( _v1, _v2, element, material ); - - } - - } else if ( element instanceof THREE.RenderableFace ) { - - _v1 = element.v1; _v2 = element.v2; _v3 = element.v3; - - if ( _v1.positionScreen.z < - 1 || _v1.positionScreen.z > 1 ) continue; - if ( _v2.positionScreen.z < - 1 || _v2.positionScreen.z > 1 ) continue; - if ( _v3.positionScreen.z < - 1 || _v3.positionScreen.z > 1 ) continue; - - _v1.positionScreen.x *= _canvasWidthHalf; _v1.positionScreen.y *= _canvasHeightHalf; - _v2.positionScreen.x *= _canvasWidthHalf; _v2.positionScreen.y *= _canvasHeightHalf; - _v3.positionScreen.x *= _canvasWidthHalf; _v3.positionScreen.y *= _canvasHeightHalf; - - if ( material.overdraw > 0 ) { - - expand( _v1.positionScreen, _v2.positionScreen, material.overdraw ); - expand( _v2.positionScreen, _v3.positionScreen, material.overdraw ); - expand( _v3.positionScreen, _v1.positionScreen, material.overdraw ); - - } - - _elemBox.setFromPoints( [ - _v1.positionScreen, - _v2.positionScreen, - _v3.positionScreen - ] ); - - if ( _clipBox.isIntersectionBox( _elemBox ) === true ) { - - renderFace3( _v1, _v2, _v3, 0, 1, 2, element, material ); - - } - - } - - /* DEBUG - setLineWidth( 1 ); - setStrokeStyle( 'rgba( 0, 255, 0, 0.5 )' ); - _context.strokeRect( _elemBox.min.x, _elemBox.min.y, _elemBox.max.x - _elemBox.min.x, _elemBox.max.y - _elemBox.min.y ); - */ - - _clearBox.union( _elemBox ); - - } - - /* DEBUG - setLineWidth( 1 ); - setStrokeStyle( 'rgba( 255, 0, 0, 0.5 )' ); - _context.strokeRect( _clearBox.min.x, _clearBox.min.y, _clearBox.max.x - _clearBox.min.x, _clearBox.max.y - _clearBox.min.y ); - */ - - _context.setTransform( 1, 0, 0, 1, 0, 0 ); - - }; - - // - - function calculateLights() { - - _ambientLight.setRGB( 0, 0, 0 ); - _directionalLights.setRGB( 0, 0, 0 ); - _pointLights.setRGB( 0, 0, 0 ); - - for ( var l = 0, ll = _lights.length; l < ll; l ++ ) { - - var light = _lights[ l ]; - var lightColor = light.color; - - if ( light instanceof THREE.AmbientLight ) { - - _ambientLight.add( lightColor ); - - } else if ( light instanceof THREE.DirectionalLight ) { - - // for sprites - - _directionalLights.add( lightColor ); - - } else if ( light instanceof THREE.PointLight ) { - - // for sprites - - _pointLights.add( lightColor ); - - } - - } - - } - - function calculateLight( position, normal, color ) { - - for ( var l = 0, ll = _lights.length; l < ll; l ++ ) { - - var light = _lights[ l ]; - - _lightColor.copy( light.color ); - - if ( light instanceof THREE.DirectionalLight ) { - - var lightPosition = _vector3.setFromMatrixPosition( light.matrixWorld ).normalize(); - - var amount = normal.dot( lightPosition ); - - if ( amount <= 0 ) continue; - - amount *= light.intensity; - - color.add( _lightColor.multiplyScalar( amount ) ); - - } else if ( light instanceof THREE.PointLight ) { - - var lightPosition = _vector3.setFromMatrixPosition( light.matrixWorld ); - - var amount = normal.dot( _vector3.subVectors( lightPosition, position ).normalize() ); - - if ( amount <= 0 ) continue; - - amount *= light.distance == 0 ? 1 : 1 - Math.min( position.distanceTo( lightPosition ) / light.distance, 1 ); - - if ( amount == 0 ) continue; - - amount *= light.intensity; - - color.add( _lightColor.multiplyScalar( amount ) ); - - } - - } - - } - - function renderSprite( v1, element, material ) { - - setOpacity( material.opacity ); - setBlending( material.blending ); - - var scaleX = element.scale.x * _canvasWidthHalf; - var scaleY = element.scale.y * _canvasHeightHalf; - - var dist = 0.5 * Math.sqrt( scaleX * scaleX + scaleY * scaleY ); // allow for rotated sprite - _elemBox.min.set( v1.x - dist, v1.y - dist ); - _elemBox.max.set( v1.x + dist, v1.y + dist ); - - if ( material instanceof THREE.SpriteMaterial ) { - - var texture = material.map; - - if ( texture !== null && texture.image !== undefined ) { - - if ( texture.hasEventListener( 'update', onTextureUpdate ) === false ) { - - if ( texture.image.width > 0 ) { - - textureToPattern( texture ); - - } - - texture.addEventListener( 'update', onTextureUpdate ); - - } - - var pattern = _patterns[ texture.id ]; - - if ( pattern !== undefined ) { - - setFillStyle( pattern ); - - } else { - - setFillStyle( 'rgba( 0, 0, 0, 1 )' ); - - } - - // - - var bitmap = texture.image; - - var ox = bitmap.width * texture.offset.x; - var oy = bitmap.height * texture.offset.y; - - var sx = bitmap.width * texture.repeat.x; - var sy = bitmap.height * texture.repeat.y; - - var cx = scaleX / sx; - var cy = scaleY / sy; - - _context.save(); - _context.translate( v1.x, v1.y ); - if ( material.rotation !== 0 ) _context.rotate( material.rotation ); - _context.translate( - scaleX / 2, - scaleY / 2 ); - _context.scale( cx, cy ); - _context.translate( - ox, - oy ); - _context.fillRect( ox, oy, sx, sy ); - _context.restore(); - - } else { - - // no texture - - setFillStyle( material.color.getStyle() ); - - _context.save(); - _context.translate( v1.x, v1.y ); - if ( material.rotation !== 0 ) _context.rotate( material.rotation ); - _context.scale( scaleX, - scaleY ); - _context.fillRect( - 0.5, - 0.5, 1, 1 ); - _context.restore(); - - } - - } else if ( material instanceof THREE.SpriteCanvasMaterial ) { - - setStrokeStyle( material.color.getStyle() ); - setFillStyle( material.color.getStyle() ); - - _context.save(); - _context.translate( v1.x, v1.y ); - if ( material.rotation !== 0 ) _context.rotate( material.rotation ); - _context.scale( scaleX, scaleY ); - - material.program( _context ); - - _context.restore(); - - } - - /* DEBUG - setStrokeStyle( 'rgb(255,255,0)' ); - _context.beginPath(); - _context.moveTo( v1.x - 10, v1.y ); - _context.lineTo( v1.x + 10, v1.y ); - _context.moveTo( v1.x, v1.y - 10 ); - _context.lineTo( v1.x, v1.y + 10 ); - _context.stroke(); - */ - - } - - function renderLine( v1, v2, element, material ) { - - setOpacity( material.opacity ); - setBlending( material.blending ); - - _context.beginPath(); - _context.moveTo( v1.positionScreen.x, v1.positionScreen.y ); - _context.lineTo( v2.positionScreen.x, v2.positionScreen.y ); - - if ( material instanceof THREE.LineBasicMaterial ) { - - setLineWidth( material.linewidth ); - setLineCap( material.linecap ); - setLineJoin( material.linejoin ); - - if ( material.vertexColors !== THREE.VertexColors ) { - - setStrokeStyle( material.color.getStyle() ); - - } else { - - var colorStyle1 = element.vertexColors[ 0 ].getStyle(); - var colorStyle2 = element.vertexColors[ 1 ].getStyle(); - - if ( colorStyle1 === colorStyle2 ) { - - setStrokeStyle( colorStyle1 ); - - } else { - - try { - - var grad = _context.createLinearGradient( - v1.positionScreen.x, - v1.positionScreen.y, - v2.positionScreen.x, - v2.positionScreen.y - ); - grad.addColorStop( 0, colorStyle1 ); - grad.addColorStop( 1, colorStyle2 ); - - } catch ( exception ) { - - grad = colorStyle1; - - } - - setStrokeStyle( grad ); - - } - - } - - _context.stroke(); - _elemBox.expandByScalar( material.linewidth * 2 ); - - } else if ( material instanceof THREE.LineDashedMaterial ) { - - setLineWidth( material.linewidth ); - setLineCap( material.linecap ); - setLineJoin( material.linejoin ); - setStrokeStyle( material.color.getStyle() ); - setLineDash( [ material.dashSize, material.gapSize ] ); - - _context.stroke(); - - _elemBox.expandByScalar( material.linewidth * 2 ); - - setLineDash( [] ); - - } - - } - - function renderFace3( v1, v2, v3, uv1, uv2, uv3, element, material ) { - - _this.info.render.vertices += 3; - _this.info.render.faces ++; - - setOpacity( material.opacity ); - setBlending( material.blending ); - - _v1x = v1.positionScreen.x; _v1y = v1.positionScreen.y; - _v2x = v2.positionScreen.x; _v2y = v2.positionScreen.y; - _v3x = v3.positionScreen.x; _v3y = v3.positionScreen.y; - - drawTriangle( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y ); - - if ( ( material instanceof THREE.MeshLambertMaterial || material instanceof THREE.MeshPhongMaterial ) && material.map === null ) { - - _diffuseColor.copy( material.color ); - _emissiveColor.copy( material.emissive ); - - if ( material.vertexColors === THREE.FaceColors ) { - - _diffuseColor.multiply( element.color ); - - } - - _color.copy( _ambientLight ); - - _centroid.copy( v1.positionWorld ).add( v2.positionWorld ).add( v3.positionWorld ).divideScalar( 3 ); - - calculateLight( _centroid, element.normalModel, _color ); - - _color.multiply( _diffuseColor ).add( _emissiveColor ); - - material.wireframe === true - ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin ) - : fillPath( _color ); - - } else if ( material instanceof THREE.MeshBasicMaterial || - material instanceof THREE.MeshLambertMaterial || - material instanceof THREE.MeshPhongMaterial ) { - - if ( material.map !== null ) { - - var mapping = material.map.mapping; - - if ( mapping === THREE.UVMapping ) { - - _uvs = element.uvs; - patternPath( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _uvs[ uv1 ].x, _uvs[ uv1 ].y, _uvs[ uv2 ].x, _uvs[ uv2 ].y, _uvs[ uv3 ].x, _uvs[ uv3 ].y, material.map ); - - } - - } else if ( material.envMap !== null ) { - - if ( material.envMap.mapping === THREE.SphericalReflectionMapping ) { - - _normal.copy( element.vertexNormalsModel[ uv1 ] ).applyMatrix3( _normalViewMatrix ); - _uv1x = 0.5 * _normal.x + 0.5; - _uv1y = 0.5 * _normal.y + 0.5; - - _normal.copy( element.vertexNormalsModel[ uv2 ] ).applyMatrix3( _normalViewMatrix ); - _uv2x = 0.5 * _normal.x + 0.5; - _uv2y = 0.5 * _normal.y + 0.5; - - _normal.copy( element.vertexNormalsModel[ uv3 ] ).applyMatrix3( _normalViewMatrix ); - _uv3x = 0.5 * _normal.x + 0.5; - _uv3y = 0.5 * _normal.y + 0.5; - - patternPath( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _uv1x, _uv1y, _uv2x, _uv2y, _uv3x, _uv3y, material.envMap ); - - } - - } else { - - _color.copy( material.color ); - - if ( material.vertexColors === THREE.FaceColors ) { - - _color.multiply( element.color ); - - } - - material.wireframe === true - ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin ) - : fillPath( _color ); - - } - - } else if ( material instanceof THREE.MeshDepthMaterial ) { - - _color.r = _color.g = _color.b = 1 - smoothstep( v1.positionScreen.z * v1.positionScreen.w, _camera.near, _camera.far ); - - material.wireframe === true - ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin ) - : fillPath( _color ); - - } else if ( material instanceof THREE.MeshNormalMaterial ) { - - _normal.copy( element.normalModel ).applyMatrix3( _normalViewMatrix ); - - _color.setRGB( _normal.x, _normal.y, _normal.z ).multiplyScalar( 0.5 ).addScalar( 0.5 ); - - material.wireframe === true - ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin ) - : fillPath( _color ); - - } else { - - _color.setRGB( 1, 1, 1 ); - - material.wireframe === true - ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin ) - : fillPath( _color ); - - } - - } - - // - - function drawTriangle( x0, y0, x1, y1, x2, y2 ) { - - _context.beginPath(); - _context.moveTo( x0, y0 ); - _context.lineTo( x1, y1 ); - _context.lineTo( x2, y2 ); - _context.closePath(); - - } - - function strokePath( color, linewidth, linecap, linejoin ) { - - setLineWidth( linewidth ); - setLineCap( linecap ); - setLineJoin( linejoin ); - setStrokeStyle( color.getStyle() ); - - _context.stroke(); - - _elemBox.expandByScalar( linewidth * 2 ); - - } - - function fillPath( color ) { - - setFillStyle( color.getStyle() ); - _context.fill(); - - } - - function onTextureUpdate ( event ) { - - textureToPattern( event.target ); - - } - - function textureToPattern( texture ) { - - if ( texture instanceof THREE.CompressedTexture ) return; - - var repeatX = texture.wrapS === THREE.RepeatWrapping; - var repeatY = texture.wrapT === THREE.RepeatWrapping; - - var image = texture.image; - - var canvas = document.createElement( 'canvas' ); - canvas.width = image.width; - canvas.height = image.height; - - var context = canvas.getContext( '2d' ); - context.setTransform( 1, 0, 0, - 1, 0, image.height ); - context.drawImage( image, 0, 0 ); - - _patterns[ texture.id ] = _context.createPattern( - canvas, repeatX === true && repeatY === true - ? 'repeat' - : repeatX === true && repeatY === false - ? 'repeat-x' - : repeatX === false && repeatY === true - ? 'repeat-y' - : 'no-repeat' - ); - - } - - function patternPath( x0, y0, x1, y1, x2, y2, u0, v0, u1, v1, u2, v2, texture ) { - - if ( texture instanceof THREE.DataTexture ) return; - - if ( texture.hasEventListener( 'update', onTextureUpdate ) === false ) { - - if ( texture.image !== undefined && texture.image.width > 0 ) { - - textureToPattern( texture ); - - } - - texture.addEventListener( 'update', onTextureUpdate ); - - } - - var pattern = _patterns[ texture.id ]; - - if ( pattern !== undefined ) { - - setFillStyle( pattern ); - - } else { - - setFillStyle( 'rgba(0,0,0,1)' ); - _context.fill(); - - return; - - } - - // http://extremelysatisfactorytotalitarianism.com/blog/?p=2120 - - var a, b, c, d, e, f, det, idet, - offsetX = texture.offset.x / texture.repeat.x, - offsetY = texture.offset.y / texture.repeat.y, - width = texture.image.width * texture.repeat.x, - height = texture.image.height * texture.repeat.y; - - u0 = ( u0 + offsetX ) * width; - v0 = ( v0 + offsetY ) * height; - - u1 = ( u1 + offsetX ) * width; - v1 = ( v1 + offsetY ) * height; - - u2 = ( u2 + offsetX ) * width; - v2 = ( v2 + offsetY ) * height; - - x1 -= x0; y1 -= y0; - x2 -= x0; y2 -= y0; - - u1 -= u0; v1 -= v0; - u2 -= u0; v2 -= v0; - - det = u1 * v2 - u2 * v1; - - if ( det === 0 ) return; - - idet = 1 / det; - - a = ( v2 * x1 - v1 * x2 ) * idet; - b = ( v2 * y1 - v1 * y2 ) * idet; - c = ( u1 * x2 - u2 * x1 ) * idet; - d = ( u1 * y2 - u2 * y1 ) * idet; - - e = x0 - a * u0 - c * v0; - f = y0 - b * u0 - d * v0; - - _context.save(); - _context.transform( a, b, c, d, e, f ); - _context.fill(); - _context.restore(); - - } - - function clipImage( x0, y0, x1, y1, x2, y2, u0, v0, u1, v1, u2, v2, image ) { - - // http://extremelysatisfactorytotalitarianism.com/blog/?p=2120 - - var a, b, c, d, e, f, det, idet, - width = image.width - 1, - height = image.height - 1; - - u0 *= width; v0 *= height; - u1 *= width; v1 *= height; - u2 *= width; v2 *= height; - - x1 -= x0; y1 -= y0; - x2 -= x0; y2 -= y0; - - u1 -= u0; v1 -= v0; - u2 -= u0; v2 -= v0; - - det = u1 * v2 - u2 * v1; - - idet = 1 / det; - - a = ( v2 * x1 - v1 * x2 ) * idet; - b = ( v2 * y1 - v1 * y2 ) * idet; - c = ( u1 * x2 - u2 * x1 ) * idet; - d = ( u1 * y2 - u2 * y1 ) * idet; - - e = x0 - a * u0 - c * v0; - f = y0 - b * u0 - d * v0; - - _context.save(); - _context.transform( a, b, c, d, e, f ); - _context.clip(); - _context.drawImage( image, 0, 0 ); - _context.restore(); - - } - - // Hide anti-alias gaps - - function expand( v1, v2, pixels ) { - - var x = v2.x - v1.x, y = v2.y - v1.y, - det = x * x + y * y, idet; - - if ( det === 0 ) return; - - idet = pixels / Math.sqrt( det ); - - x *= idet; y *= idet; - - v2.x += x; v2.y += y; - v1.x -= x; v1.y -= y; - - } - - // Context cached methods. - - function setOpacity( value ) { - - if ( _contextGlobalAlpha !== value ) { - - _context.globalAlpha = value; - _contextGlobalAlpha = value; - - } - - } - - function setBlending( value ) { - - if ( _contextGlobalCompositeOperation !== value ) { - - if ( value === THREE.NormalBlending ) { - - _context.globalCompositeOperation = 'source-over'; - - } else if ( value === THREE.AdditiveBlending ) { - - _context.globalCompositeOperation = 'lighter'; - - } else if ( value === THREE.SubtractiveBlending ) { - - _context.globalCompositeOperation = 'darker'; - - } - - _contextGlobalCompositeOperation = value; - - } - - } - - function setLineWidth( value ) { - - if ( _contextLineWidth !== value ) { - - _context.lineWidth = value; - _contextLineWidth = value; - - } - - } - - function setLineCap( value ) { - - // "butt", "round", "square" - - if ( _contextLineCap !== value ) { - - _context.lineCap = value; - _contextLineCap = value; - - } - - } - - function setLineJoin( value ) { - - // "round", "bevel", "miter" - - if ( _contextLineJoin !== value ) { - - _context.lineJoin = value; - _contextLineJoin = value; - - } - - } - - function setStrokeStyle( value ) { - - if ( _contextStrokeStyle !== value ) { - - _context.strokeStyle = value; - _contextStrokeStyle = value; - - } - - } - - function setFillStyle( value ) { - - if ( _contextFillStyle !== value ) { - - _context.fillStyle = value; - _contextFillStyle = value; - - } - - } - - function setLineDash( value ) { - - if ( _contextLineDash.length !== value.length ) { - - _context.setLineDash( value ); - _contextLineDash = value; - - } - - } - -}; diff --git a/lib/canvas_rendering/jquery-2.1.3.min.js b/lib/canvas_rendering/jquery-2.1.3.min.js deleted file mode 100644 index 25714ed2..00000000 --- a/lib/canvas_rendering/jquery-2.1.3.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! jQuery v2.1.3 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */ -!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l=a.document,m="2.1.3",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){return!n.isArray(a)&&a-parseFloat(a)+1>=0},isPlainObject:function(a){return"object"!==n.type(a)||a.nodeType||n.isWindow(a)?!1:a.constructor&&!j.call(a.constructor.prototype,"isPrototypeOf")?!1:!0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=l.createElement("script"),b.text=a,l.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:k}),n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=hb(),z=hb(),A=hb(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},eb=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fb){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function gb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+rb(o[l]);w=ab.test(a)&&pb(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function hb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ib(a){return a[u]=!0,a}function jb(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function kb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function lb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function nb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function ob(a){return ib(function(b){return b=+b,ib(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pb(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=gb.support={},f=gb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=gb.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",eb,!1):e.attachEvent&&e.attachEvent("onunload",eb)),p=!f(g),c.attributes=jb(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=jb(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=jb(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(jb(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),jb(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&jb(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return lb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?lb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},gb.matches=function(a,b){return gb(a,null,null,b)},gb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return gb(b,n,null,[a]).length>0},gb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},gb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},gb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},gb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=gb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=gb.selectors={cacheLength:50,createPseudo:ib,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||gb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&gb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=gb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||gb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ib(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ib(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ib(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ib(function(a){return function(b){return gb(a,b).length>0}}),contains:ib(function(a){return a=a.replace(cb,db),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ib(function(a){return W.test(a||"")||gb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:ob(function(){return[0]}),last:ob(function(a,b){return[b-1]}),eq:ob(function(a,b,c){return[0>c?c+b:c]}),even:ob(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:ob(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:ob(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:ob(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function sb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function tb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ub(a,b,c){for(var d=0,e=b.length;e>d;d++)gb(a,b[d],c);return c}function vb(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wb(a,b,c,d,e,f){return d&&!d[u]&&(d=wb(d)),e&&!e[u]&&(e=wb(e,f)),ib(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ub(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:vb(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=vb(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=vb(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sb(function(a){return a===b},h,!0),l=sb(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sb(tb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wb(i>1&&tb(m),i>1&&rb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xb(a.slice(i,e)),f>e&&xb(a=a.slice(e)),f>e&&rb(a))}m.push(c)}return tb(m)}function yb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=vb(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&gb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ib(f):f}return h=gb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,yb(e,d)),f.selector=a}return f},i=gb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&pb(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&rb(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&pb(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=jb(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),jb(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||kb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&jb(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||kb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),jb(function(a){return null==a.getAttribute("disabled")})||kb(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),gb}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return g.call(b,a)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=n.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:l,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}return d=l.getElementById(c[2]),d&&d.parentNode&&(this.length=1,this[0]=d),this.context=l,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};A.prototype=n.fn,y=n(l);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?"string"==typeof a?g.call(n(a),this[0]):g.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,"parentNode")},parentsUntil:function(a,b,c){return n.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return n.dir(a,"nextSibling")},prevAll:function(a){return n.dir(a,"previousSibling")},nextUntil:function(a,b,c){return n.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return n.dir(a,"previousSibling",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(C[a]||n.unique(e),B.test(a)&&e.reverse()),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return n.each(a.match(E)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(b=a.memory&&l,c=!0,g=e||0,e=0,f=h.length,d=!0;h&&f>g;g++)if(h[g].apply(l[0],l[1])===!1&&a.stopOnFalse){b=!1;break}d=!1,h&&(i?i.length&&j(i.shift()):b?h=[]:k.disable())},k={add:function(){if(h){var c=h.length;!function g(b){n.each(b,function(b,c){var d=n.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&g(c)})}(arguments),d?f=h.length:b&&(e=c,j(b))}return this},remove:function(){return h&&n.each(arguments,function(a,b){var c;while((c=n.inArray(b,h,c))>-1)h.splice(c,1),d&&(f>=c&&f--,g>=c&&g--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],f=0,this},disable:function(){return h=i=b=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,b||k.disable(),this},locked:function(){return!i},fireWith:function(a,b){return!h||c&&!i||(b=b||[],b=[a,b.slice?b.slice():b],d?i.push(b):j(b)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!c}};return k},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(H.resolveWith(l,[n]),n.fn.triggerHandler&&(n(l).triggerHandler("ready"),n(l).off("ready"))))}});function I(){l.removeEventListener("DOMContentLoaded",I,!1),a.removeEventListener("load",I,!1),n.ready()}n.ready.promise=function(b){return H||(H=n.Deferred(),"complete"===l.readyState?setTimeout(n.ready):(l.addEventListener("DOMContentLoaded",I,!1),a.addEventListener("load",I,!1))),H.promise(b)},n.ready.promise();var J=n.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)n.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f};n.acceptData=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function K(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=n.expando+K.uid++}K.uid=1,K.accepts=n.acceptData,K.prototype={key:function(a){if(!K.accepts(a))return 0;var b={},c=a[this.expando];if(!c){c=K.uid++;try{b[this.expando]={value:c},Object.defineProperties(a,b)}catch(d){b[this.expando]=c,n.extend(a,b)}}return this.cache[c]||(this.cache[c]={}),c},set:function(a,b,c){var d,e=this.key(a),f=this.cache[e];if("string"==typeof b)f[b]=c;else if(n.isEmptyObject(f))n.extend(this.cache[e],b);else for(d in b)f[d]=b[d];return f},get:function(a,b){var c=this.cache[this.key(a)];return void 0===b?c:c[b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=this.key(a),g=this.cache[f];if(void 0===b)this.cache[f]={};else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in g?d=[b,e]:(d=e,d=d in g?[d]:d.match(E)||[])),c=d.length;while(c--)delete g[d[c]]}},hasData:function(a){return!n.isEmptyObject(this.cache[a[this.expando]]||{})},discard:function(a){a[this.expando]&&delete this.cache[a[this.expando]]}};var L=new K,M=new K,N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(O,"-$1").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}M.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return M.hasData(a)||L.hasData(a)},data:function(a,b,c){return M.access(a,b,c) -},removeData:function(a,b){M.remove(a,b)},_data:function(a,b,c){return L.access(a,b,c)},_removeData:function(a,b){L.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=M.get(f),1===f.nodeType&&!L.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));L.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){M.set(this,a)}):J(this,function(b){var c,d=n.camelCase(a);if(f&&void 0===b){if(c=M.get(f,a),void 0!==c)return c;if(c=M.get(f,d),void 0!==c)return c;if(c=P(f,d,void 0),void 0!==c)return c}else this.each(function(){var c=M.get(this,d);M.set(this,d,b),-1!==a.indexOf("-")&&void 0!==c&&M.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){M.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=L.get(a,b),c&&(!d||n.isArray(c)?d=L.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return L.get(a,c)||L.access(a,c,{empty:n.Callbacks("once memory").add(function(){L.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthx",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U="undefined";k.focusinBubbles="onfocusin"in a;var V=/^key/,W=/^(?:mouse|pointer|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return l.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof n!==U&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(E)||[""],j=b.length;while(j--)h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&(delete r.handle,L.remove(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,m,o,p=[d||l],q=j.call(b,"type")?b.type:b,r=j.call(b,"namespace")?b.namespace.split("."):[];if(g=h=d=d||l,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+n.event.triggered)&&(q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),k=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},e||!o.trigger||o.trigger.apply(d,c)!==!1)){if(!e&&!o.noBubble&&!n.isWindow(d)){for(i=o.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||l)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:o.bindType||q,m=(L.get(g,"events")||{})[b.type]&&L.get(g,"handle"),m&&m.apply(g,c),m=k&&g[k],m&&m.apply&&n.acceptData(g)&&(b.result=m.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!n.acceptData(d)||k&&n.isFunction(d[q])&&!n.isWindow(d)&&(h=d[k],h&&(d[k]=null),n.event.triggered=q,d[q](),n.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(L.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!==this;i=i.parentNode||this)if(i.disabled!==!0||"click"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>=0:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]*)\/>/gi,bb=/<([\w:]+)/,cb=/<|&#?\w+;/,db=/<(?:script|style|link)/i,eb=/checked\s*(?:[^=]|=\s*.checked.)/i,fb=/^$|\/(?:java|ecma)script/i,gb=/^true\/(.*)/,hb=/^\s*\s*$/g,ib={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ib.optgroup=ib.option,ib.tbody=ib.tfoot=ib.colgroup=ib.caption=ib.thead,ib.th=ib.td;function jb(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function kb(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function lb(a){var b=gb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function mb(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],"globalEval",!b||L.get(b[c],"globalEval"))}function nb(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=n.extend({},h),M.set(b,i))}}function ob(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||"*"):a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function pb(a,b){var c=b.nodeName.toLowerCase();"input"===c&&T.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}n.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=ob(h),f=ob(a),d=0,e=f.length;e>d;d++)pb(f[d],g[d]);if(b)if(c)for(f=f||ob(a),g=g||ob(h),d=0,e=f.length;e>d;d++)nb(f[d],g[d]);else nb(a,h);return g=ob(h,"script"),g.length>0&&mb(g,!i&&ob(a,"script")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,o=a.length;o>m;m++)if(e=a[m],e||0===e)if("object"===n.type(e))n.merge(l,e.nodeType?[e]:e);else if(cb.test(e)){f=f||k.appendChild(b.createElement("div")),g=(bb.exec(e)||["",""])[1].toLowerCase(),h=ib[g]||ib._default,f.innerHTML=h[1]+e.replace(ab,"<$1>")+h[2],j=h[0];while(j--)f=f.lastChild;n.merge(l,f.childNodes),f=k.firstChild,f.textContent=""}else l.push(b.createTextNode(e));k.textContent="",m=0;while(e=l[m++])if((!d||-1===n.inArray(e,d))&&(i=n.contains(e.ownerDocument,e),f=ob(k.appendChild(e),"script"),i&&mb(f),c)){j=0;while(e=f[j++])fb.test(e.type||"")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f=n.event.special,g=0;void 0!==(c=a[g]);g++){if(n.acceptData(c)&&(e=c[L.expando],e&&(b=L.cache[e]))){if(b.events)for(d in b.events)f[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);L.cache[e]&&delete L.cache[e]}delete M.cache[c[M.expando]]}}}),n.fn.extend({text:function(a){return J(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(ob(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&mb(ob(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(ob(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return J(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!db.test(a)&&!ib[(bb.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(ab,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ob(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(ob(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,m=this,o=l-1,p=a[0],q=n.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&eb.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(c=n.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=n.map(ob(c,"script"),kb),g=f.length;l>j;j++)h=c,j!==o&&(h=n.clone(h,!0,!0),g&&n.merge(f,ob(h,"script"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,n.map(f,lb),j=0;g>j;j++)h=f[j],fb.test(h.type||"")&&!L.access(h,"globalEval")&&n.contains(i,h)&&(h.src?n._evalUrl&&n._evalUrl(h.src):n.globalEval(h.textContent.replace(hb,"")))}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),n(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qb,rb={};function sb(b,c){var d,e=n(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:n.css(e[0],"display");return e.detach(),f}function tb(a){var b=l,c=rb[a];return c||(c=sb(a,b),"none"!==c&&c||(qb=(qb||n(" - - - - - - - Introduction - Long Tutorial - - -
- -

Send in comments, suggestions and issues to 3dufhelp@gmail.com .

- -
Designs From Literature
- Check the various designs from microfluidic literature recreated in 3DµF can be found - here. -
Usage
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
del
- Delete Feature
F
- Reset Canvas
Esc
- Activate Select Tool/ Deselect Selected Components
ctrl+C , ctrl+V
- Activate Component Copy Mode
ctrl+Z
- Undo Last Edit
ctrl+A
- Select All
ctrl+S
- Save JSON file
left click
- Place Feature
right click
- Select Feature
mouse scroll
- Zoom
arrow keys
- Pan
- - -
- -
- - - - -
-

Drag and drop the DXF file on the canvas

-
-
- -
-
-
- - -
-
-
-
- - -
-
- - -
-

Generate Design of Experiments for a Single Component

-
-
- -
-
- - - - - - -
-
- - -
-
- - -
- -

Rename:

-
-
- - -
-
- -

Resize:

- -
-
- - - Input is not a number! -
-
- - - Input is not a number! -
-
-
-
- - -
-
- -
- -

Insert Text:

-
-
- - -
-
-
-
- - -
-
- -
- -

Drag Drop the DXF file containing border to import:

-
- -
- -
-
-
- - - -
-
- -
- -
Change All Components:
-
- - - - - - - - -
SelectNameChange
-
- - -
-
- - -
-

Send your design for fabrication at DAMP LAB

-
-
- -
Enter your contact information:
-
-
- - -
-
- - -
-
- -

Learn more about the DAMP LAB fabrication service here.

-
- - - - - - -
-
- - -
-
- - -
-
- -
- - - - - - - diff --git a/public/nouislider.min.css b/public/nouislider.min.css deleted file mode 100644 index 73e0c63f..00000000 --- a/public/nouislider.min.css +++ /dev/null @@ -1,208 +0,0 @@ -/*! noUiSlider - 8.0.1 - 2015-06-29 19:11:23 */ - -.noUi-target, -.noUi-target * { - -webkit-touch-callout: none; - -webkit-user-select: none; - -ms-touch-action: none; - -ms-user-select: none; - -moz-user-select: none; - -moz-box-sizing: border-box; - box-sizing: border-box; -} -.noUi-target { - position: relative; - direction: ltr; -} -.noUi-base { - width: 100%; - height: 100%; - position: relative; - z-index: 1; -} -.noUi-origin { - position: absolute; - right: 0; - top: 0; - left: 0; - bottom: 0; -} -.noUi-handle { - position: relative; - z-index: 1; -} -.noUi-stacking .noUi-handle { - z-index: 10; -} -.noUi-state-tap .noUi-origin { - -webkit-transition: left 0.3s, top 0.3s; - transition: left 0.3s, top 0.3s; -} -.noUi-state-drag * { - cursor: inherit !important; -} -.noUi-base { - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); -} -.noUi-horizontal { - height: 18px; -} -.noUi-horizontal .noUi-handle { - width: 34px; - height: 28px; - left: -17px; - top: -6px; -} -.noUi-vertical { - width: 18px; -} -.noUi-vertical .noUi-handle { - width: 28px; - height: 34px; - left: -6px; - top: -17px; -} -.noUi-background { - background: #fafafa; - box-shadow: inset 0 1px 1px #f0f0f0; -} -.noUi-connect { - background: #3fb8af; - box-shadow: inset 0 0 3px rgba(51, 51, 51, 0.45); - -webkit-transition: background 450ms; - transition: background 450ms; -} -.noUi-origin { - border-radius: 2px; -} -.noUi-target { - border-radius: 4px; - border: 1px solid #d3d3d3; - box-shadow: inset 0 1px 1px #f0f0f0, 0 3px 6px -5px #bbb; -} -.noUi-target.noUi-connect { - box-shadow: inset 0 0 3px rgba(51, 51, 51, 0.45), 0 3px 6px -5px #bbb; -} -.noUi-dragable { - cursor: w-resize; -} -.noUi-vertical .noUi-dragable { - cursor: n-resize; -} -.noUi-handle { - border: 1px solid #d9d9d9; - border-radius: 3px; - background: #fff; - cursor: default; - box-shadow: inset 0 0 1px #fff, inset 0 1px 7px #ebebeb, 0 3px 6px -3px #bbb; -} -.noUi-active { - box-shadow: inset 0 0 1px #fff, inset 0 1px 7px #ddd, 0 3px 6px -3px #bbb; -} -.noUi-handle:after, -.noUi-handle:before { - content: ""; - display: block; - position: absolute; - height: 14px; - width: 1px; - background: #e8e7e6; - left: 14px; - top: 6px; -} -.noUi-handle:after { - left: 17px; -} -.noUi-vertical .noUi-handle:after, -.noUi-vertical .noUi-handle:before { - width: 14px; - height: 1px; - left: 6px; - top: 14px; -} -.noUi-vertical .noUi-handle:after { - top: 17px; -} -[disabled] .noUi-connect, -[disabled].noUi-connect { - background: #b8b8b8; -} -[disabled] .noUi-handle, -[disabled].noUi-origin { - cursor: not-allowed; -} -.noUi-pips, -.noUi-pips * { - -moz-box-sizing: border-box; - box-sizing: border-box; -} -.noUi-pips { - position: absolute; - font: 400 12px Arial; - color: #999; -} -.noUi-value { - width: 40px; - position: absolute; - text-align: center; -} -.noUi-value-sub { - color: #ccc; - font-size: 10px; -} -.noUi-marker { - position: absolute; - background: #ccc; -} -.noUi-marker-large, -.noUi-marker-sub { - background: #aaa; -} -.noUi-pips-horizontal { - padding: 10px 0; - height: 50px; - top: 100%; - left: 0; - width: 100%; -} -.noUi-value-horizontal { - margin-left: -20px; - padding-top: 20px; -} -.noUi-value-horizontal.noUi-value-sub { - padding-top: 15px; -} -.noUi-marker-horizontal.noUi-marker { - margin-left: -1px; - width: 2px; - height: 5px; -} -.noUi-marker-horizontal.noUi-marker-sub { - height: 10px; -} -.noUi-marker-horizontal.noUi-marker-large { - height: 15px; -} -.noUi-pips-vertical { - padding: 0 10px; - height: 100%; - top: 0; - left: 100%; -} -.noUi-value-vertical { - width: 15px; - margin-left: 20px; - margin-top: -5px; -} -.noUi-marker-vertical.noUi-marker { - width: 5px; - height: 2px; - margin-top: -1px; -} -.noUi-marker-vertical.noUi-marker-sub { - width: 10px; -} -.noUi-marker-vertical.noUi-marker-large { - width: 15px; -} diff --git a/public/orbit_bundle.js b/public/orbit_bundle.js deleted file mode 100644 index 06d41c53..00000000 --- a/public/orbit_bundle.js +++ /dev/null @@ -1,1282 +0,0 @@ -(function e(t, n, r) { - function s(o, u) { - if (!n[o]) { - if (!t[o]) { - const a = typeof require === "function" && require; - if (!u && a) return a(o, !0); - if (i) return i(o, !0); - const f = new Error("Cannot find module '" + o + "'"); - throw ((f.code = "MODULE_NOT_FOUND"), f); - } - const l = (n[o] = { exports: {} }); - t[o][0].call( - l.exports, - function (e) { - const n = t[o][1][e]; - return s(n || e); - }, - l, - l.exports, - e, - t, - n, - r - ); - } - return n[o].exports; - } - var i = typeof require === "function" && require; - for (let o = 0; o < r.length; o++) s(r[o]); - return s; -})( - { - 1: [ - function (require, module, exports) { - /** - * @author qiao / https://github.com/qiao - * @author mrdoob / http://mrdoob.com - * @author alteredq / http://alteredqualia.com/ - * @author WestLangley / http://github.com/WestLangley - * @author erich666 / http://erichaines.com - */ - /* global THREE, console */ - - // This set of controls performs orbiting, dollying (zooming), and panning. It maintains - // the "up" direction as +Y, unlike the TrackballControls. Touch on tablet and phones is - // supported. - // - // Orbit - left mouse / touch: one finger move - // Zoom - middle mouse, or mousewheel / touch: two finger spread or squish - // Pan - right mouse, or arrow keys / touch: three finter swipe - - "use strict"; - - THREE.OrbitControls = function (object, domElement) { - this.object = object; - this.domElement = domElement !== undefined ? domElement : document; - - // API - - // Set to false to disable this control - this.enabled = true; - - // "target" sets the location of focus, where the control orbits around - // and where it pans with respect to. - this.target = new THREE.Vector3(); - - // center is old, deprecated; use "target" instead - this.center = this.target; - - // This option actually enables dollying in and out; left as "zoom" for - // backwards compatibility - this.noZoom = false; - this.zoomSpeed = 1.0; - - // Limits to how far you can dolly in and out ( PerspectiveCamera only ) - this.minDistance = 0; - this.maxDistance = Infinity; - - // Limits to how far you can zoom in and out ( OrthographicCamera only ) - this.minZoom = 0; - this.maxZoom = Infinity; - - // Set to true to disable this control - this.noRotate = false; - this.rotateSpeed = 1.0; - - // Set to true to disable this control - this.noPan = false; - this.keyPanSpeed = 7.0; // pixels moved per arrow key push - - // Set to true to automatically rotate around the target - this.autoRotate = false; - this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60 - - // How far you can orbit vertically, upper and lower limits. - // Range is 0 to Math.PI radians. - this.minPolarAngle = 0; // radians - this.maxPolarAngle = Math.PI; // radians - - // How far you can orbit horizontally, upper and lower limits. - // If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ]. - this.minAzimuthAngle = -Math.PI; // radians - this.maxAzimuthAngle = Math.PI; // radians - - // Set to true to disable use of the keys - this.noKeys = false; - - // The four arrow keys - this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 }; - - // Mouse buttons - // this.mouseButtons = { ORBIT: THREE.MOUSE.LEFT, ZOOM: THREE.MOUSE.MIDDLE, PAN: THREE.MOUSE.RIGHT }; - this.mouseButtons = { ORBIT: THREE.MOUSE.RIGHT, PAN: THREE.MOUSE.MIDDLE }; - - /// ///////// - // internals - - const scope = this; - - const EPS = 0.000001; - - const rotateStart = new THREE.Vector2(); - const rotateEnd = new THREE.Vector2(); - const rotateDelta = new THREE.Vector2(); - - const panStart = new THREE.Vector2(); - const panEnd = new THREE.Vector2(); - const panDelta = new THREE.Vector2(); - const panOffset = new THREE.Vector3(); - - const offset = new THREE.Vector3(); - - const dollyStart = new THREE.Vector2(); - const dollyEnd = new THREE.Vector2(); - const dollyDelta = new THREE.Vector2(); - - let theta; - let phi; - let phiDelta = 0; - let thetaDelta = 0; - let scale = 1; - const pan = new THREE.Vector3(); - - const lastPosition = new THREE.Vector3(); - const lastQuaternion = new THREE.Quaternion(); - - const STATE = { NONE: -1, ROTATE: 0, DOLLY: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_DOLLY: 4, TOUCH_PAN: 5 }; - - let state = STATE.NONE; - - // for reset - - this.target0 = this.target.clone(); - this.position0 = this.object.position.clone(); - this.zoom0 = this.object.zoom; - - // so camera.up is the orbit axis - - const quat = new THREE.Quaternion().setFromUnitVectors(object.up, new THREE.Vector3(0, 1, 0)); - const quatInverse = quat.clone().inverse(); - - // events - - const changeEvent = { type: "change" }; - const startEvent = { type: "start" }; - const endEvent = { type: "end" }; - - this.rotateLeft = function (angle) { - if (angle === undefined) { - angle = getAutoRotationAngle(); - } - - thetaDelta -= angle; - }; - - this.rotateUp = function (angle) { - if (angle === undefined) { - angle = getAutoRotationAngle(); - } - - phiDelta -= angle; - }; - - // pass in distance in world space to move left - this.panLeft = function (distance) { - const te = this.object.matrix.elements; - - // get X column of matrix - panOffset.set(te[0], te[1], te[2]); - panOffset.multiplyScalar(-distance); - - pan.add(panOffset); - }; - - // pass in distance in world space to move up - this.panUp = function (distance) { - const te = this.object.matrix.elements; - - // get Y column of matrix - panOffset.set(te[4], te[5], te[6]); - panOffset.multiplyScalar(distance); - - pan.add(panOffset); - }; - - // pass in x,y of change desired in pixel space, - // right and down are positive - this.pan = function (deltaX, deltaY) { - const element = scope.domElement === document ? scope.domElement.body : scope.domElement; - - if (scope.object instanceof THREE.PerspectiveCamera) { - // perspective - const position = scope.object.position; - const offset = position.clone().sub(scope.target); - let targetDistance = offset.length(); - - // half of the fov is center to top of screen - targetDistance *= Math.tan(((scope.object.fov / 2) * Math.PI) / 180.0); - - // we actually don't use screenWidth, since perspective camera is fixed to screen height - scope.panLeft((2 * deltaX * targetDistance) / element.clientHeight); - scope.panUp((2 * deltaY * targetDistance) / element.clientHeight); - } else if (scope.object instanceof THREE.OrthographicCamera) { - // orthographic - scope.panLeft((deltaX * (scope.object.right - scope.object.left)) / element.clientWidth); - scope.panUp((deltaY * (scope.object.top - scope.object.bottom)) / element.clientHeight); - } else { - // camera neither orthographic or perspective - console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled."); - } - }; - - this.dollyIn = function (dollyScale) { - if (dollyScale === undefined) { - dollyScale = getZoomScale(); - } - - if (scope.object instanceof THREE.PerspectiveCamera) { - scale /= dollyScale; - } else if (scope.object instanceof THREE.OrthographicCamera) { - scope.object.zoom = Math.max(this.minZoom, Math.min(this.maxZoom, this.object.zoom * dollyScale)); - scope.object.updateProjectionMatrix(); - scope.dispatchEvent(changeEvent); - } else { - console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."); - } - }; - - this.dollyOut = function (dollyScale) { - if (dollyScale === undefined) { - dollyScale = getZoomScale(); - } - - if (scope.object instanceof THREE.PerspectiveCamera) { - scale *= dollyScale; - } else if (scope.object instanceof THREE.OrthographicCamera) { - scope.object.zoom = Math.max(this.minZoom, Math.min(this.maxZoom, this.object.zoom / dollyScale)); - scope.object.updateProjectionMatrix(); - scope.dispatchEvent(changeEvent); - } else { - console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."); - } - }; - - this.update = function () { - const position = this.object.position; - - offset.copy(position).sub(this.target); - - // rotate offset to "y-axis-is-up" space - offset.applyQuaternion(quat); - - // angle from z-axis around y-axis - - theta = Math.atan2(offset.x, offset.z); - - // angle from y-axis - - phi = Math.atan2(Math.sqrt(offset.x * offset.x + offset.z * offset.z), offset.y); - - if (this.autoRotate && state === STATE.NONE) { - this.rotateLeft(getAutoRotationAngle()); - } - - theta += thetaDelta; - phi += phiDelta; - - // restrict theta to be between desired limits - theta = Math.max(this.minAzimuthAngle, Math.min(this.maxAzimuthAngle, theta)); - - // restrict phi to be between desired limits - phi = Math.max(this.minPolarAngle, Math.min(this.maxPolarAngle, phi)); - - // restrict phi to be betwee EPS and PI-EPS - phi = Math.max(EPS, Math.min(Math.PI - EPS, phi)); - - let radius = offset.length() * scale; - - // restrict radius to be between desired limits - radius = Math.max(this.minDistance, Math.min(this.maxDistance, radius)); - - // move target to panned location - this.target.add(pan); - - offset.x = radius * Math.sin(phi) * Math.sin(theta); - offset.y = radius * Math.cos(phi); - offset.z = radius * Math.sin(phi) * Math.cos(theta); - - // rotate offset back to "camera-up-vector-is-up" space - offset.applyQuaternion(quatInverse); - - position.copy(this.target).add(offset); - - this.object.lookAt(this.target); - - thetaDelta = 0; - phiDelta = 0; - scale = 1; - pan.set(0, 0, 0); - - // update condition is: - // min(camera displacement, camera rotation in radians)^2 > EPS - // using small-angle approximation cos(x/2) = 1 - x^2 / 8 - - if (lastPosition.distanceToSquared(this.object.position) > EPS || 8 * (1 - lastQuaternion.dot(this.object.quaternion)) > EPS) { - this.dispatchEvent(changeEvent); - - lastPosition.copy(this.object.position); - lastQuaternion.copy(this.object.quaternion); - } - }; - - this.reset = function () { - state = STATE.NONE; - - this.target.copy(this.target0); - this.object.position.copy(this.position0); - this.object.zoom = this.zoom0; - - this.object.updateProjectionMatrix(); - this.dispatchEvent(changeEvent); - - this.update(); - }; - - this.getPolarAngle = function () { - return phi; - }; - - this.getAzimuthalAngle = function () { - return theta; - }; - - function getAutoRotationAngle() { - return ((2 * Math.PI) / 60 / 60) * scope.autoRotateSpeed; - } - - function getZoomScale() { - return Math.pow(0.95, scope.zoomSpeed); - } - - function onMouseDown(event) { - if (scope.enabled === false) return; - event.preventDefault(); - - if (event.button === scope.mouseButtons.ORBIT) { - if (scope.noRotate === true) return; - - state = STATE.ROTATE; - - rotateStart.set(event.clientX, event.clientY); - } else if (event.button === scope.mouseButtons.ZOOM) { - if (scope.noZoom === true) return; - - state = STATE.DOLLY; - - dollyStart.set(event.clientX, event.clientY); - } else if (event.button === scope.mouseButtons.PAN || event.button == THREE.MOUSE.LEFT) { - if (scope.noPan === true) return; - - state = STATE.PAN; - - panStart.set(event.clientX, event.clientY); - } - - if (state !== STATE.NONE) { - document.addEventListener("mousemove", onMouseMove, false); - document.addEventListener("mouseup", onMouseUp, false); - scope.dispatchEvent(startEvent); - } - } - - function onMouseMove(event) { - if (scope.enabled === false) return; - - event.preventDefault(); - - const element = scope.domElement === document ? scope.domElement.body : scope.domElement; - - if (state === STATE.ROTATE) { - if (scope.noRotate === true) return; - - rotateEnd.set(event.clientX, event.clientY); - rotateDelta.subVectors(rotateEnd, rotateStart); - - // rotating across whole screen goes 360 degrees around - scope.rotateLeft(((2 * Math.PI * rotateDelta.x) / element.clientWidth) * scope.rotateSpeed); - - // rotating up and down along whole screen attempts to go 360, but limited to 180 - scope.rotateUp(((2 * Math.PI * rotateDelta.y) / element.clientHeight) * scope.rotateSpeed); - - rotateStart.copy(rotateEnd); - } else if (state === STATE.DOLLY) { - if (scope.noZoom === true) return; - - dollyEnd.set(event.clientX, event.clientY); - dollyDelta.subVectors(dollyEnd, dollyStart); - - if (dollyDelta.y > 0) { - scope.dollyIn(); - } else if (dollyDelta.y < 0) { - scope.dollyOut(); - } - - dollyStart.copy(dollyEnd); - } else if (state === STATE.PAN) { - if (scope.noPan === true) return; - - panEnd.set(event.clientX, event.clientY); - panDelta.subVectors(panEnd, panStart); - - scope.pan(panDelta.x, panDelta.y); - - panStart.copy(panEnd); - } - - if (state !== STATE.NONE) scope.update(); - } - - function onMouseUp() /* event */ { - if (scope.enabled === false) return; - - document.removeEventListener("mousemove", onMouseMove, false); - document.removeEventListener("mouseup", onMouseUp, false); - scope.dispatchEvent(endEvent); - state = STATE.NONE; - } - - function onMouseWheel(event) { - if (scope.enabled === false || scope.noZoom === true || state !== STATE.NONE) return; - - event.preventDefault(); - event.stopPropagation(); - - let delta = 0; - - if (event.wheelDelta !== undefined) { - // WebKit / Opera / Explorer 9 - - delta = event.wheelDelta; - } else if (event.detail !== undefined) { - // Firefox - - delta = -event.detail; - } - - if (delta > 0) { - scope.dollyOut(); - } else if (delta < 0) { - scope.dollyIn(); - } - - scope.update(); - scope.dispatchEvent(startEvent); - scope.dispatchEvent(endEvent); - } - - function onKeyDown(event) { - if (scope.enabled === false || scope.noKeys === true || scope.noPan === true) return; - - switch (event.keyCode) { - case scope.keys.UP: - scope.pan(0, scope.keyPanSpeed); - scope.update(); - break; - - case scope.keys.BOTTOM: - scope.pan(0, -scope.keyPanSpeed); - scope.update(); - break; - - case scope.keys.LEFT: - scope.pan(scope.keyPanSpeed, 0); - scope.update(); - break; - - case scope.keys.RIGHT: - scope.pan(-scope.keyPanSpeed, 0); - scope.update(); - break; - } - } - - function touchstart(event) { - if (scope.enabled === false) return; - - switch (event.touches.length) { - case 1: - // one-fingered touch: rotate - - if (scope.noRotate === true) return; - - state = STATE.TOUCH_ROTATE; - - rotateStart.set(event.touches[0].pageX, event.touches[0].pageY); - break; - - case 2: - // two-fingered touch: dolly - - if (scope.noZoom === true) return; - - state = STATE.TOUCH_DOLLY; - - var dx = event.touches[0].pageX - event.touches[1].pageX; - var dy = event.touches[0].pageY - event.touches[1].pageY; - var distance = Math.sqrt(dx * dx + dy * dy); - dollyStart.set(0, distance); - break; - - case 3: - // three-fingered touch: pan - - if (scope.noPan === true) return; - - state = STATE.TOUCH_PAN; - - panStart.set(event.touches[0].pageX, event.touches[0].pageY); - break; - - default: - state = STATE.NONE; - } - - if (state !== STATE.NONE) scope.dispatchEvent(startEvent); - } - - function touchmove(event) { - if (scope.enabled === false) return; - - event.preventDefault(); - event.stopPropagation(); - - const element = scope.domElement === document ? scope.domElement.body : scope.domElement; - - switch (event.touches.length) { - case 1: - // one-fingered touch: rotate - - if (scope.noRotate === true) return; - if (state !== STATE.TOUCH_ROTATE) return; - - rotateEnd.set(event.touches[0].pageX, event.touches[0].pageY); - rotateDelta.subVectors(rotateEnd, rotateStart); - - // rotating across whole screen goes 360 degrees around - scope.rotateLeft(((2 * Math.PI * rotateDelta.x) / element.clientWidth) * scope.rotateSpeed); - // rotating up and down along whole screen attempts to go 360, but limited to 180 - scope.rotateUp(((2 * Math.PI * rotateDelta.y) / element.clientHeight) * scope.rotateSpeed); - - rotateStart.copy(rotateEnd); - - scope.update(); - break; - - case 2: - // two-fingered touch: dolly - - if (scope.noZoom === true) return; - if (state !== STATE.TOUCH_DOLLY) return; - - var dx = event.touches[0].pageX - event.touches[1].pageX; - var dy = event.touches[0].pageY - event.touches[1].pageY; - var distance = Math.sqrt(dx * dx + dy * dy); - - dollyEnd.set(0, distance); - dollyDelta.subVectors(dollyEnd, dollyStart); - - if (dollyDelta.y > 0) { - scope.dollyOut(); - } else if (dollyDelta.y < 0) { - scope.dollyIn(); - } - - dollyStart.copy(dollyEnd); - - scope.update(); - break; - - case 3: - // three-fingered touch: pan - - if (scope.noPan === true) return; - if (state !== STATE.TOUCH_PAN) return; - - panEnd.set(event.touches[0].pageX, event.touches[0].pageY); - panDelta.subVectors(panEnd, panStart); - - scope.pan(panDelta.x, panDelta.y); - - panStart.copy(panEnd); - - scope.update(); - break; - - default: - state = STATE.NONE; - } - } - - function touchend() /* event */ { - if (scope.enabled === false) return; - - scope.dispatchEvent(endEvent); - state = STATE.NONE; - } - - this.domElement.addEventListener( - "contextmenu", - function (event) { - event.preventDefault(); - }, - false - ); - this.domElement.addEventListener("mousedown", onMouseDown, false); - this.domElement.addEventListener("mousewheel", onMouseWheel, false); - this.domElement.addEventListener("DOMMouseScroll", onMouseWheel, false); // firefox - - this.domElement.addEventListener("touchstart", touchstart, false); - this.domElement.addEventListener("touchend", touchend, false); - this.domElement.addEventListener("touchmove", touchmove, false); - - window.addEventListener("keydown", onKeyDown, false); - - // force an update at start - this.update(); - }; - - THREE.OrbitControls.prototype = Object.create(THREE.EventDispatcher.prototype); - THREE.OrbitControls.prototype.constructor = THREE.OrbitControls; - }, - {} - ], - 2: [ - function (require, module, exports) { - /** - * Based on https://github.com/mrdoob/three.js/blob/a72347515fa34e892f7a9bfa66a34fdc0df55954/examples/js/exporters/STLExporter.js - * Tested on r68 and r70 - * @author jcarletto / https://github.com/jcarletto27 - * @author kjlubick / https://github.com/kjlubick - * @author kovacsv / http://kovacsv.hu/ - * @author mrdoob / http://mrdoob.com/ - - */ - "use strict"; - - THREE.STLExporter = function () {}; - - THREE.STLExporter.prototype = { - constructor: THREE.STLExporter, - - parse: (function () { - const vector = new THREE.Vector3(); - const normalMatrixWorld = new THREE.Matrix3(); - - return function (scene) { - let output = ""; - - output += "solid exported\n"; - - scene.traverse(function (object) { - if (object instanceof THREE.Mesh) { - const geometry = object.geometry; - const matrixWorld = object.matrixWorld; - const mesh = object; - - if (geometry instanceof THREE.Geometry) { - const vertices = geometry.vertices; - const faces = geometry.faces; - - normalMatrixWorld.getNormalMatrix(matrixWorld); - - for (let i = 0, l = faces.length; i < l; i++) { - const face = faces[i]; - - vector.copy(face.normal).applyMatrix3(normalMatrixWorld).normalize(); - - output += "\tfacet normal " + vector.x + " " + vector.y + " " + vector.z + "\n"; - output += "\t\touter loop\n"; - - const indices = [face.a, face.b, face.c]; - - for (let j = 0; j < 3; j++) { - const vertexIndex = indices[j]; - if (mesh.geometry.skinIndices.length == 0) { - vector.copy(vertices[vertexIndex]).applyMatrix4(matrixWorld); - output += "\t\t\tvertex " + vector.x + " " + vector.y + " " + vector.z + "\n"; - } else { - vector.copy(vertices[vertexIndex]); // .applyMatrix4( matrixWorld ); - - // see https://github.com/mrdoob/three.js/issues/3187 - boneIndices = []; - boneIndices[0] = mesh.geometry.skinIndices[vertexIndex].x; - boneIndices[1] = mesh.geometry.skinIndices[vertexIndex].y; - boneIndices[2] = mesh.geometry.skinIndices[vertexIndex].z; - boneIndices[3] = mesh.geometry.skinIndices[vertexIndex].w; - - weights = []; - weights[0] = mesh.geometry.skinWeights[vertexIndex].x; - weights[1] = mesh.geometry.skinWeights[vertexIndex].y; - weights[2] = mesh.geometry.skinWeights[vertexIndex].z; - weights[3] = mesh.geometry.skinWeights[vertexIndex].w; - - inverses = []; - inverses[0] = mesh.skeleton.boneInverses[boneIndices[0]]; - inverses[1] = mesh.skeleton.boneInverses[boneIndices[1]]; - inverses[2] = mesh.skeleton.boneInverses[boneIndices[2]]; - inverses[3] = mesh.skeleton.boneInverses[boneIndices[3]]; - - skinMatrices = []; - skinMatrices[0] = mesh.skeleton.bones[boneIndices[0]].matrixWorld; - skinMatrices[1] = mesh.skeleton.bones[boneIndices[1]].matrixWorld; - skinMatrices[2] = mesh.skeleton.bones[boneIndices[2]].matrixWorld; - skinMatrices[3] = mesh.skeleton.bones[boneIndices[3]].matrixWorld; - - // this checks to see if the mesh has any morphTargets - jc - if (mesh.geometry.morphTargets !== "undefined") { - morphMatricesX = []; - morphMatricesY = []; - morphMatricesZ = []; - morphMatricesInfluence = []; - - for (var mt = 0; mt < mesh.geometry.morphTargets.length; mt++) { - // collect the needed vertex info - jc - morphMatricesX[mt] = mesh.geometry.morphTargets[mt].vertices[vertexIndex].x; - morphMatricesY[mt] = mesh.geometry.morphTargets[mt].vertices[vertexIndex].y; - morphMatricesZ[mt] = mesh.geometry.morphTargets[mt].vertices[vertexIndex].z; - morphMatricesInfluence[mt] = mesh.morphTargetInfluences[mt]; - } - } - const finalVector = new THREE.Vector4(); - - if (mesh.geometry.morphTargets !== "undefined") { - var morphVector = new THREE.Vector4(vector.x, vector.y, vector.z); - - for (var mt = 0; mt < mesh.geometry.morphTargets.length; mt++) { - // not pretty, but it gets the job done - jc - morphVector.lerp( - new THREE.Vector4(morphMatricesX[mt], morphMatricesY[mt], morphMatricesZ[mt], 1), - morphMatricesInfluence[mt] - ); - } - } - - for (let k = 0; k < 4; k++) { - if (mesh.geometry.morphTargets !== "undefined") { - var tempVector = new THREE.Vector4(morphVector.x, morphVector.y, morphVector.z); - } else { - var tempVector = new THREE.Vector4(vector.x, vector.y, vector.z); - } - tempVector.multiplyScalar(weights[k]); - // the inverse takes the vector into local bone space - // which is then transformed to the appropriate world space - tempVector.applyMatrix4(inverses[k]).applyMatrix4(skinMatrices[k]); - finalVector.add(tempVector); - } - - output += "\t\t\tvertex " + finalVector.x + " " + finalVector.y + " " + finalVector.z + "\n"; - } - } - output += "\t\tendloop\n"; - output += "\tendfacet\n"; - } - } - } - }); - - output += "endsolid exported\n"; - - return output; - }; - })() - }; - - function saveSTL(scene, name) { - const exporter = new THREE.STLExporter(); - const stlString = exporter.parse(scene); - - const blob = new Blob([stlString], { - type: "text/plain" - }); - - saveAs(blob, name + ".stl"); - } - const exporter = new THREE.STLExporter(); - const exportString = function exportString(output, filename) { - const blob = new Blob([output], { - type: "text/plain" - }); - const objectURL = URL.createObjectURL(blob); - - const link = document.createElement("a"); - link.href = objectURL; - link.download = filename || "data.json"; - link.target = "_blank"; - link.click(); - }; - - module.exports.saveSTL = saveSTL; - module.exports.exportString = exportString; - }, - {} - ], - 3: [ - function (require, module, exports) { - "use strict"; - - const device_json = JSON.parse( - '{"name":"My Device","params":{"width":75800,"height":51000},"layers":[{"name":"flow","color":"indigo","params":{"z_offset":0,"flip":false},"features":{"6bb96ad0-3d80-11e5-898a-2de600a0e2af":{"id":"6bb96ad0-3d80-11e5-898a-2de600a0e2af","name":"New Port","type":"Port","params":{"position":[30000,40000],"radius1":700,"radius2":700,"height":100}},"6bb96ad1-3d80-11e5-898a-2de600a0e2af":{"id":"6bb96ad1-3d80-11e5-898a-2de600a0e2af","name":"New Port","type":"Port","params":{"position":[40000,40000],"radius1":700,"radius2":700,"height":100}},"6bb96ad2-3d80-11e5-898a-2de600a0e2af":{"id":"6bb96ad2-3d80-11e5-898a-2de600a0e2af","name":"New Port","type":"Port","params":{"position":[50000,40000],"radius1":700,"radius2":700,"height":100}},"6bb96ad3-3d80-11e5-898a-2de600a0e2af":{"id":"6bb96ad3-3d80-11e5-898a-2de600a0e2af","name":"New Port","type":"Port","params":{"position":[20000,40000],"radius1":700,"radius2":700,"height":100}},"6bb991e0-3d80-11e5-898a-2de600a0e2af":{"id":"6bb991e0-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[20000,40000],"end":[20000,35000],"width":400,"height":100}},"6bb991e1-3d80-11e5-898a-2de600a0e2af":{"id":"6bb991e1-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[20000,38000],"end":[17000,38000],"width":400,"height":100}},"6bb991e2-3d80-11e5-898a-2de600a0e2af":{"id":"6bb991e2-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[17000,38000],"end":[17000,35000],"width":400,"height":100}},"6bb991e3-3d80-11e5-898a-2de600a0e2af":{"id":"6bb991e3-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[20000,35000],"end":[20000,20000],"width":400,"height":100}},"6bb991e4-3d80-11e5-898a-2de600a0e2af":{"id":"6bb991e4-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[20000,20000],"end":[10000,10000],"width":400,"height":100}},"6bb991e5-3d80-11e5-898a-2de600a0e2af":{"id":"6bb991e5-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[17000,35000],"end":[15000,30000],"width":400,"height":100}},"6bb991e6-3d80-11e5-898a-2de600a0e2af":{"id":"6bb991e6-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[15000,30000],"end":[10000,30000],"width":400,"height":100}},"6bb991e7-3d80-11e5-898a-2de600a0e2af":{"id":"6bb991e7-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[10000,30000],"end":[10000,28000],"width":400,"height":100}},"6bb991e8-3d80-11e5-898a-2de600a0e2af":{"id":"6bb991e8-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[10000,28000],"end":[15000,28000],"width":400,"height":100}},"6bb991e9-3d80-11e5-898a-2de600a0e2af":{"id":"6bb991e9-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[15000,28000],"end":[15000,25000],"width":400,"height":100}},"6bb991ea-3d80-11e5-898a-2de600a0e2af":{"id":"6bb991ea-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[15000,25000],"end":[8000,25000],"width":400,"height":100}},"6bb991eb-3d80-11e5-898a-2de600a0e2af":{"id":"6bb991eb-3d80-11e5-898a-2de600a0e2af","name":"New Port","type":"Port","params":{"position":[8000,25000],"radius1":700,"radius2":700,"height":100}},"6bb991ec-3d80-11e5-898a-2de600a0e2af":{"id":"6bb991ec-3d80-11e5-898a-2de600a0e2af","name":"New Port","type":"Port","params":{"position":[10000,10000],"radius1":700,"radius2":700,"height":100}},"6bb991ed-3d80-11e5-898a-2de600a0e2af":{"id":"6bb991ed-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[30000,40000],"end":[30000,20000],"width":400,"height":100}},"6bb991ee-3d80-11e5-898a-2de600a0e2af":{"id":"6bb991ee-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[30000,20000],"end":[20000,10000],"width":400,"height":100}},"6bb991ef-3d80-11e5-898a-2de600a0e2af":{"id":"6bb991ef-3d80-11e5-898a-2de600a0e2af","name":"New Port","type":"Port","params":{"position":[20000,10000],"radius1":700,"radius2":700,"height":100}},"6bb991f0-3d80-11e5-898a-2de600a0e2af":{"id":"6bb991f0-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[30000,38000],"end":[27000,38000],"width":400,"height":100}},"6bb991f1-3d80-11e5-898a-2de600a0e2af":{"id":"6bb991f1-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[27000,38000],"end":[27000,30000],"width":400,"height":100}},"6bb991f2-3d80-11e5-898a-2de600a0e2af":{"id":"6bb991f2-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[27000,30000],"end":[22000,30000],"width":400,"height":100}},"6bb991f3-3d80-11e5-898a-2de600a0e2af":{"id":"6bb991f3-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[22000,30000],"end":[22000,28000],"width":400,"height":100}},"6bb991f4-3d80-11e5-898a-2de600a0e2af":{"id":"6bb991f4-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[22000,28000],"end":[27000,28000],"width":400,"height":100}},"6bb991f5-3d80-11e5-898a-2de600a0e2af":{"id":"6bb991f5-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[27000,28000],"end":[27000,26000],"width":400,"height":100}},"6bb991f6-3d80-11e5-898a-2de600a0e2af":{"id":"6bb991f6-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[27000,26000],"end":[22000,26000],"width":400,"height":100}},"6bb991f7-3d80-11e5-898a-2de600a0e2af":{"id":"6bb991f7-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[22000,26000],"end":[22000,24000],"width":400,"height":100}},"6bb991f8-3d80-11e5-898a-2de600a0e2af":{"id":"6bb991f8-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[22000,24000],"end":[27000,24000],"width":400,"height":100}},"6bb991f9-3d80-11e5-898a-2de600a0e2af":{"id":"6bb991f9-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[27000,24000],"end":[27000,22000],"width":400,"height":100}},"6bb991fa-3d80-11e5-898a-2de600a0e2af":{"id":"6bb991fa-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[27000,22000],"end":[22000,22000],"width":400,"height":100}},"6bb991fb-3d80-11e5-898a-2de600a0e2af":{"id":"6bb991fb-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[22000,22000],"end":[22000,20000],"width":400,"height":100}},"6bb991fc-3d80-11e5-898a-2de600a0e2af":{"id":"6bb991fc-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[22000,20000],"end":[25000,20000],"width":400,"height":100}},"6bb991fd-3d80-11e5-898a-2de600a0e2af":{"id":"6bb991fd-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[25000,20000],"end":[25000,17000],"width":400,"height":100}},"6bb991fe-3d80-11e5-898a-2de600a0e2af":{"id":"6bb991fe-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[25000,17000],"end":[21000,17000],"width":400,"height":100}},"6bb9b8f0-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9b8f0-3d80-11e5-898a-2de600a0e2af","name":"New Port","type":"Port","params":{"position":[21000,17000],"radius1":700,"radius2":700,"height":100}},"6bb9b8f1-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9b8f1-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[40000,40000],"end":[40000,20000],"width":400,"height":100}},"6bb9b8f2-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9b8f2-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[40000,20000],"end":[50000,10000],"width":400,"height":100}},"6bb9b8f3-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9b8f3-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[40000,38000],"end":[43000,38000],"width":400,"height":100}},"6bb9b8f4-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9b8f4-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[43000,38000],"end":[43000,30000],"width":400,"height":100}},"6bb9b8f5-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9b8f5-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[43000,30000],"end":[48000,30000],"width":400,"height":100}},"6bb9b8f6-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9b8f6-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[48000,30000],"end":[48000,28000],"width":400,"height":100}},"6bb9b8f7-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9b8f7-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[48000,28000],"end":[43000,28000],"width":400,"height":100}},"6bb9b8f8-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9b8f8-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[43000,28000],"end":[43000,26000],"width":400,"height":100}},"6bb9b8f9-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9b8f9-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[43000,26000],"end":[48000,26000],"width":400,"height":100}},"6bb9b8fa-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9b8fa-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[48000,26000],"end":[48000,24000],"width":400,"height":100}},"6bb9b8fb-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9b8fb-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[48000,24000],"end":[43000,24000],"width":400,"height":100}},"6bb9b8fc-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9b8fc-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[43000,24000],"end":[43000,22000],"width":400,"height":100}},"6bb9b8fd-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9b8fd-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[43000,22000],"end":[48000,22000],"width":400,"height":100}},"6bb9b8fe-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9b8fe-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[48000,22000],"end":[48000,20000],"width":400,"height":100}},"6bb9b8ff-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9b8ff-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[48000,20000],"end":[45000,20000],"width":400,"height":100}},"6bb9b900-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9b900-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[45000,20000],"end":[45000,17000],"width":400,"height":100}},"6bb9b901-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9b901-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[45000,17000],"end":[49000,17000],"width":400,"height":100}},"6bb9b902-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9b902-3d80-11e5-898a-2de600a0e2af","name":"New Port","type":"Port","params":{"position":[50000,10000],"radius1":700,"radius2":700,"height":100}},"6bb9b903-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9b903-3d80-11e5-898a-2de600a0e2af","name":"New Port","type":"Port","params":{"position":[49000,17000],"radius1":700,"radius2":700,"height":100}},"6bb9b904-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9b904-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[50000,40000],"end":[50000,20000],"width":400,"height":100}},"6bb9b905-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9b905-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[50000,20000],"end":[60000,10000],"width":400,"height":100}},"6bb9b906-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9b906-3d80-11e5-898a-2de600a0e2af","name":"New Port","type":"Port","params":{"position":[60000,10000],"radius1":700,"radius2":700,"height":100}},"6bb9e000-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9e000-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[50000,38000],"end":[53000,38000],"width":400,"height":100}},"6bb9e001-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9e001-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[53000,38000],"end":[53000,35000],"width":400,"height":100}},"6bb9e002-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9e002-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[53000,35000],"end":[55000,30000],"width":400,"height":100}},"6bb9e003-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9e003-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[55000,30000],"end":[60000,30000],"width":400,"height":100}},"6bb9e004-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9e004-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[60000,30000],"end":[60000,28000],"width":400,"height":100}},"6bb9e005-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9e005-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[60000,28000],"end":[55000,28000],"width":400,"height":100}},"6bb9e006-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9e006-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[55000,28000],"end":[55000,25000],"width":400,"height":100}},"6bb9e007-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9e007-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[55000,25000],"end":[62000,25000],"width":400,"height":100}},"6bb9e008-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9e008-3d80-11e5-898a-2de600a0e2af","name":"New Port","type":"Port","params":{"position":[62000,25000],"radius1":700,"radius2":700,"height":100}},"6bb9e009-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9e009-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[15000,15000],"end":[15000,12000],"width":400,"height":100}},"6bb9e00a-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9e00a-3d80-11e5-898a-2de600a0e2af","name":"New Via","type":"Via","params":{"position":[15000,12000],"radius1":800,"radius2":700,"height":1000}},"6bb9e00b-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9e00b-3d80-11e5-898a-2de600a0e2af","name":"New Via","type":"Via","params":{"position":[26000,12000],"radius1":800,"radius2":700,"height":1000}},"6bb9e00c-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9e00c-3d80-11e5-898a-2de600a0e2af","name":"New Via","type":"Via","params":{"position":[44000,12000],"radius1":800,"radius2":700,"height":1000}},"6bb9e00d-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9e00d-3d80-11e5-898a-2de600a0e2af","name":"New Via","type":"Via","params":{"position":[55000,12000],"radius1":800,"radius2":700,"height":1000}},"6bb9e00e-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9e00e-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[55000,12000],"end":[55000,15000],"width":400,"height":100}},"6bb9e00f-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9e00f-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[26000,12000],"end":[30000,10000],"width":400,"height":100}},"6bb9e010-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9e010-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[44000,12000],"end":[40000,10000],"width":400,"height":100}},"6bb9e011-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9e011-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[40000,10000],"end":[38000,7000],"width":400,"height":100}},"6bb9e012-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9e012-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[30000,10000],"end":[32000,7000],"width":400,"height":100}},"6bb9e013-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9e013-3d80-11e5-898a-2de600a0e2af","name":"New Port","type":"Port","params":{"position":[32000,7000],"radius1":700,"radius2":700,"height":100}},"6bb9e014-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9e014-3d80-11e5-898a-2de600a0e2af","name":"New Port","type":"Port","params":{"position":[38000,7000],"radius1":700,"radius2":700,"height":100}},"6bb9e015-3d80-11e5-898a-2de600a0e2af":{"id":"6bb9e015-3d80-11e5-898a-2de600a0e2af","name":"New CircleValve","type":"CircleValve","params":{"position":[35000,10000],"radius1":1400,"radius2":1200,"height":800}},"6bba0710-3d80-11e5-898a-2de600a0e2af":{"id":"6bba0710-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[35000,10000],"end":[35000,30000],"width":400,"height":100}},"6bba0711-3d80-11e5-898a-2de600a0e2af":{"id":"6bba0711-3d80-11e5-898a-2de600a0e2af","name":"New Port","type":"Port","params":{"position":[35000,30000],"radius1":700,"radius2":700,"height":100}},"6bba0712-3d80-11e5-898a-2de600a0e2af":{"id":"6bba0712-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[35000,17000],"end":[38000,23000],"width":400,"height":100}},"6bba0713-3d80-11e5-898a-2de600a0e2af":{"id":"6bba0713-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[38000,23000],"end":[36000,25000],"width":400,"height":100}},"6bba0714-3d80-11e5-898a-2de600a0e2af":{"id":"6bba0714-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[36000,25000],"end":[35000,30000],"width":400,"height":100}},"6bba0715-3d80-11e5-898a-2de600a0e2af":{"id":"6bba0715-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[35000,17000],"end":[32000,23000],"width":400,"height":100}},"6bba0716-3d80-11e5-898a-2de600a0e2af":{"id":"6bba0716-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[32000,23000],"end":[34000,25000],"width":400,"height":100}},"6bba0717-3d80-11e5-898a-2de600a0e2af":{"id":"6bba0717-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[34000,25000],"end":[35000,30000],"width":400,"height":100}},"6bba0718-3d80-11e5-898a-2de600a0e2af":{"id":"6bba0718-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[32000,23000],"end":[35000,24000],"width":400,"height":100}},"6bba0719-3d80-11e5-898a-2de600a0e2af":{"id":"6bba0719-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[38000,23000],"end":[35000,24000],"width":400,"height":100}},"6bba071a-3d80-11e5-898a-2de600a0e2af":{"id":"6bba071a-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[25000,20000],"end":[28000,20000],"width":400,"height":100}},"6bba071b-3d80-11e5-898a-2de600a0e2af":{"id":"6bba071b-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[28000,20000],"end":[28000,22000],"width":400,"height":100}},"6bba071c-3d80-11e5-898a-2de600a0e2af":{"id":"6bba071c-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[28000,22000],"end":[27000,22000],"width":400,"height":100}},"6bba071d-3d80-11e5-898a-2de600a0e2af":{"id":"6bba071d-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[45000,20000],"end":[42000,20000],"width":400,"height":100}},"6bba071e-3d80-11e5-898a-2de600a0e2af":{"id":"6bba071e-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[42000,20000],"end":[42000,22000],"width":400,"height":100}},"6bba071f-3d80-11e5-898a-2de600a0e2af":{"id":"6bba071f-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[42000,22000],"end":[44000,22000],"width":400,"height":100}},"8d30ec10-3d80-11e5-898a-2de600a0e2af":{"id":"8d30ec10-3d80-11e5-898a-2de600a0e2af","name":"New Via","type":"Via","params":{"position":[35000,30000],"radius1":800,"radius2":700,"height":1000}},"9b26fd00-3d80-11e5-898a-2de600a0e2af":{"id":"9b26fd00-3d80-11e5-898a-2de600a0e2af","name":"New Via","type":"Via","params":{"position":[32000,20000],"radius1":800,"radius2":700,"height":1000}},"9c3deb40-3d80-11e5-898a-2de600a0e2af":{"id":"9c3deb40-3d80-11e5-898a-2de600a0e2af","name":"New Via","type":"Via","params":{"position":[38000,20000],"radius1":800,"radius2":700,"height":1000}}}},{"name":"control","color":"red","params":{"z_offset":1200,"flip":true},"features":{"6bba0720-3d80-11e5-898a-2de600a0e2af":{"id":"6bba0720-3d80-11e5-898a-2de600a0e2af","name":"New CircleValve","type":"CircleValve","params":{"position":[20000,34000],"radius1":1400,"radius2":1200,"height":800}},"6bba0721-3d80-11e5-898a-2de600a0e2af":{"id":"6bba0721-3d80-11e5-898a-2de600a0e2af","name":"New CircleValve","type":"CircleValve","params":{"position":[30000,34000],"radius1":1400,"radius2":1200,"height":800}},"6bba0722-3d80-11e5-898a-2de600a0e2af":{"id":"6bba0722-3d80-11e5-898a-2de600a0e2af","name":"New CircleValve","type":"CircleValve","params":{"position":[40000,34000],"radius1":1400,"radius2":1200,"height":800}},"6bba0723-3d80-11e5-898a-2de600a0e2af":{"id":"6bba0723-3d80-11e5-898a-2de600a0e2af","name":"New CircleValve","type":"CircleValve","params":{"position":[50000,34000],"radius1":1400,"radius2":1200,"height":800}},"6bba0724-3d80-11e5-898a-2de600a0e2af":{"id":"6bba0724-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[20000,34000],"end":[24000,34000],"width":400,"height":100}},"6bba0725-3d80-11e5-898a-2de600a0e2af":{"id":"6bba0725-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[24000,34000],"end":[24000,47000],"width":400,"height":100}},"6bba0726-3d80-11e5-898a-2de600a0e2af":{"id":"6bba0726-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[30000,34000],"end":[34000,34000],"width":400,"height":100}},"6bba0727-3d80-11e5-898a-2de600a0e2af":{"id":"6bba0727-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[34000,34000],"end":[34000,47000],"width":400,"height":100}},"6bba0728-3d80-11e5-898a-2de600a0e2af":{"id":"6bba0728-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[40000,34000],"end":[37000,34000],"width":400,"height":100}},"6bba0729-3d80-11e5-898a-2de600a0e2af":{"id":"6bba0729-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[37000,34000],"end":[36000,34000],"width":400,"height":100}},"6bba072a-3d80-11e5-898a-2de600a0e2af":{"id":"6bba072a-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[36000,34000],"end":[36000,47000],"width":400,"height":100}},"6bba072b-3d80-11e5-898a-2de600a0e2af":{"id":"6bba072b-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[50000,34000],"end":[46000,34000],"width":400,"height":100}},"6bba072c-3d80-11e5-898a-2de600a0e2af":{"id":"6bba072c-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[46000,34000],"end":[46000,47000],"width":400,"height":100}},"6bba072d-3d80-11e5-898a-2de600a0e2af":{"id":"6bba072d-3d80-11e5-898a-2de600a0e2af","name":"New Port","type":"Port","params":{"position":[24000,47000],"radius1":700,"radius2":700,"height":100}},"6bba072e-3d80-11e5-898a-2de600a0e2af":{"id":"6bba072e-3d80-11e5-898a-2de600a0e2af","name":"New Port","type":"Port","params":{"position":[34000,47000],"radius1":700,"radius2":700,"height":100}},"6bba072f-3d80-11e5-898a-2de600a0e2af":{"id":"6bba072f-3d80-11e5-898a-2de600a0e2af","name":"New Port","type":"Port","params":{"position":[36000,47000],"radius1":700,"radius2":700,"height":100}},"6bba0730-3d80-11e5-898a-2de600a0e2af":{"id":"6bba0730-3d80-11e5-898a-2de600a0e2af","name":"New Port","type":"Port","params":{"position":[46000,47000],"radius1":700,"radius2":700,"height":100}},"6bba2e20-3d80-11e5-898a-2de600a0e2af":{"id":"6bba2e20-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[15000,12000],"end":[26000,12000],"width":400,"height":100}},"6bba2e21-3d80-11e5-898a-2de600a0e2af":{"id":"6bba2e21-3d80-11e5-898a-2de600a0e2af","name":"New Channel","type":"Channel","params":{"start":[44000,12000],"end":[55000,12000],"width":400,"height":100}},"6bba2e22-3d80-11e5-898a-2de600a0e2af":{"id":"6bba2e22-3d80-11e5-898a-2de600a0e2af","name":"New Port","type":"Port","params":{"position":[15000,12000],"radius1":700,"radius2":700,"height":100}},"6bba2e23-3d80-11e5-898a-2de600a0e2af":{"id":"6bba2e23-3d80-11e5-898a-2de600a0e2af","name":"New Port","type":"Port","params":{"position":[26000,12000],"radius1":700,"radius2":700,"height":100}},"6bba2e24-3d80-11e5-898a-2de600a0e2af":{"id":"6bba2e24-3d80-11e5-898a-2de600a0e2af","name":"New Port","type":"Port","params":{"position":[44000,12000],"radius1":700,"radius2":700,"height":100}},"6bba2e25-3d80-11e5-898a-2de600a0e2af":{"id":"6bba2e25-3d80-11e5-898a-2de600a0e2af","name":"New Port","type":"Port","params":{"position":[55000,12000],"radius1":700,"radius2":700,"height":100}},"6bba2e26-3d80-11e5-898a-2de600a0e2af":{"id":"6bba2e26-3d80-11e5-898a-2de600a0e2af","name":"New Port","type":"Port","params":{"position":[25000,21000],"radius1":700,"radius2":700,"height":100}},"6bba2e27-3d80-11e5-898a-2de600a0e2af":{"id":"6bba2e27-3d80-11e5-898a-2de600a0e2af","name":"New Port","type":"Port","params":{"position":[45000,21000],"radius1":700,"radius2":700,"height":100}}}}],"groups":[],"defaults":{}}' - ); - - module.exports = device_json; - }, - {} - ], - 4: [ - function (require, module, exports) { - "use strict"; - - const OrbitControls = require("./OrbitControls"); - const device_json = require("./device_json"); - const STLExporter = require("./STLExporter"); - const saveSTL = STLExporter.saveSTL; - - const container = document.getElementById("renderContainer"); - let camera, controls, scene, renderer; - - const redMaterial = new THREE.MeshLambertMaterial({ color: 0xf44336, shading: THREE.FlatShading }); - const blueMaterial = new THREE.MeshLambertMaterial({ color: 0x3f51b5, shading: THREE.FlatShading }); - const whiteMaterial = new THREE.MeshBasicMaterial({ color: 0xffffff, shading: THREE.FlatShading }); - const purpleMaterial = new THREE.MeshLambertMaterial({ color: 0x673ab7, shading: THREE.FlatShading }); - const greyMaterial = new THREE.MeshLambertMaterial({ color: 0x9e9e9e, shading: THREE.FlatShading }); - const slideMaterial = new THREE.MeshLambertMaterial({ color: 0xffffff, opacity: 0.1, transparent: true }); - const holderMaterial = greyMaterial; - const groundMaterial = new THREE.MeshBasicMaterial({ color: 0x414141, shading: THREE.FlatShading }); - const backgroundColor = 0xeeeeee; - - const INTERLOCK_TOLERANCE = 0.125; - const HOLDER_BORDER_WIDTH = 0.41; - const SLIDE_Z_OFFSET = 1.2; - const HOLDER_SKIRT_WIDTH = 0.8; - const HOLDER_SKIRT_HEIGHT = 0.2; - const CORNER_DISTANCE = 10; - const SLIDE_THICKNESS = 1.2; - - let mockup = null; - const mockupScene = null; - let layers = null; - - const layerMaterials = { - indigo: blueMaterial, - red: redMaterial, - purple: purpleMaterial, - grey: greyMaterial - }; - - function getFeatureMaterial(feature, layer) { - const colorString = layer.color; - if (colorString && layerMaterials.hasOwnProperty(colorString)) { - return layerMaterials[colorString]; - } else return layerMaterials.grey; - } - - init(); - render(); - loadJSON(device_json); - - function loadJSON(json) { - sanitizeJSON(json); - mockup = renderMockup(json); - layers = renderLayers(json); - showMockup(json); - // showLayer(0); - } - - function showLayer(index) { - scene.add(layers[index]); - render(); - // saveSTL(scene, "layer"); - } - - function showMockup(json) { - scene.add(mockup); - render(); - // saveSTL(scene, "test"); - } - - function renderFeatures(layer, z_offset) { - const renderedFeatures = new THREE.Group(); - for (const featureID in layer.features) { - const feature = layer.features[featureID]; - renderedFeatures.add(renderFeature(feature, layer, z_offset)); - } - return renderedFeatures; - } - - function renderFeature(feature, layer, z_offset) { - const type = feature.type; - let renderedFeature; - - if (type == "Channel") renderedFeature = Channel(feature, layer, z_offset); - else if (type == "CircleValve") renderedFeature = CircleValve(feature, layer, z_offset); - else if (type == "Via") renderedFeature = Via(feature, layer, z_offset); - else if (type == "Port") renderedFeature = Port(feature, layer, z_offset); - else console.log("Feature type not recognized: " + type); - - return renderedFeature; - } - - function renderLayers(json) { - const renderedLayers = []; - for (let i = 0; i < json.layers.length; i++) { - renderedLayers.push(renderLayer(json, i)); - } - return renderedLayers; - } - - function renderLayer(json, layerIndex) { - console.log("Rendering layer: " + layerIndex); - const width = json.params.width; - const height = json.params.height; - const layer = json.layers[layerIndex]; - const renderedFeatures = new THREE.Group(); - const renderedLayer = new THREE.Group(); - renderedFeatures.add(renderFeatures(layer, 0)); - if (layer.params.flip) { - flipLayer(renderedFeatures, height, layer.params.z_offset); - } - renderedLayer.add(renderedFeatures); - renderedLayer.add(SlideHolder(width, height, SLIDE_THICKNESS, true)); - return renderedLayer; - } - - function flipLayer(layer, height, z_offset) { - layer.rotation.x += Math.PI; - layer.position.y += height; - layer.position.z += z_offset; - } - - function renderMockup(json) { - mockup = null; - const renderedMockup = new THREE.Group(); - const layers = json.layers; - for (let i = 0; i < layers.length; i++) { - const layer = layers[i]; - const renderedLayer = renderFeatures(layer, layer.params.z_offset); - renderedMockup.add(renderedLayer); - } - const renderedHolder = SlideHolder(json.params.width, json.params.height, SLIDE_THICKNESS, true); - renderedMockup.add(renderedHolder); - return renderedMockup; - } - - function animate() { - requestAnimationFrame(animate); - controls.update(); - } - - function init() { - camera = new THREE.PerspectiveCamera(60, container.clientWidth / container.clientHeight, 1, 1000); - camera.position.z = 100; - controls = new THREE.OrbitControls(camera); - controls.damping = 0.2; - controls.addEventListener("change", render); - - scene = new THREE.Scene(); - - const slide = Slide(70, 50, 1); - slide.position.z -= 1; - // scene.add(slide); - - // world - - const flow = { - params: { - z_offset: 0, - flip: false - }, - color: "indigo" - }; - - const control = { - params: { - z_offset: 1, - flip: true - }, - color: "red" - }; - - const via = { - params: { - position: [5, 10], - height: 0.6, - radius1: 0.6, - radius2: 0.4 - } - }; - - const channel = { - params: { - start: [0, 0], - end: [10, 10], - height: 0.4, - width: 0.6 - } - }; - - const boxGeom = new THREE.BoxGeometry(1, 1, 1); - - const viaMesh = Via(via, control); - const channelMesh = Channel(channel, flow); - - const group = new THREE.Group(); - - // console.log(viaMesh.geometry); - - // scene.add(viaMesh); - // scene.add(channelMesh); - - // lights - const light1 = new THREE.DirectionalLight(0xffffff); - light1.position.set(1, 1, 1); - scene.add(light1); - - const light2 = new THREE.DirectionalLight(0x002288); - light2.position.set(-1, -1, -1); - scene.add(light2); - - const light3 = new THREE.AmbientLight(0x222222); - scene.add(light3); - - // renderer - - renderer = new THREE.WebGLRenderer({ antialias: true }); - renderer.setSize(container.clientWidth, container.clientHeight); - renderer.setClearColor(backgroundColor, 1); - - container.appendChild(renderer.domElement); - - window.addEventListener("resize", onWindowResize, false); - - // controls.update(); - - // scene.remove(slide); - // saveSTL(scene, "foo"); - // scene.add(slide); - - // setupCamera(35,25,50.8, 500); - } - - function onWindowResize() { - camera.aspect = container.clientWidth / container.clientHeight; - camera.updateProjectionMatrix(); - renderer.setSize(container.clientWidth, container.clientHeight); - render(); - } - - function render() { - renderer.render(scene, camera); - } - - function setupCamera(centerX, centerY, deviceHeight, pixelHeight) { - camera.position.z = getCameraDistance(deviceHeight, pixelHeight); - controls.panLeft(-centerX); - controls.panUp(-centerY + deviceHeight); - controls.update(); - } - - function DevicePlane(width, height, offset) { - const plane = new THREE.PlaneBufferGeometry(width, height); - const material = whiteMaterial; - const mesh = new THREE.Mesh(plane, material); - const matrix = new THREE.Matrix4(); - mesh.geometry.applyMatrix(matrix.makeTranslation(width / 2, height / 2, -offset)); - return mesh; - } - - function GroundPlane(width, height) { - const plane = new THREE.PlaneGeometry(width, height); - const material = groundMaterial; - const mesh = new THREE.Mesh(plane, material); - return mesh; - } - - function Via(via, layer, z_offset) { - const radius1 = via.params.radius1; - const radius2 = via.params.radius2; - const height = via.params.height; - const position = via.params.position; - var z_offset = layer.params.z_offset; - const flip = layer.params.flip; - const geom = ConeFeature(position, radius1, radius2, height, flip, z_offset); - const material = getFeatureMaterial(via, layer); - const mesh = new THREE.Mesh(geom, material); - return mesh; - } - - function Port(port, layer, z_offset) { - const radius1 = port.params.radius1; - const radius2 = port.params.radius2; - const height = port.params.height; - const position = port.params.position; - var z_offset = layer.params.z_offset; - const flip = layer.params.flip; - const geom = ConeFeature(position, radius1, radius2, height, flip, z_offset); - const material = getFeatureMaterial(port, layer); - const mesh = new THREE.Mesh(geom, material); - return mesh; - } - - function CircleValve(circleValve, layer, z_offset) { - const radius1 = circleValve.params.radius1; - const radius2 = circleValve.params.radius2; - const height = circleValve.params.height; - const position = circleValve.params.position; - var z_offset = layer.params.z_offset; - const flip = layer.params.flip; - const geom = ConeFeature(position, radius1, radius2, height, flip, z_offset); - const material = getFeatureMaterial(circleValve, layer); - const mesh = new THREE.Mesh(geom, material); - return mesh; - } - - function ConeFeature(position, radius1, radius2, height, flip, z_offset) { - const cone = Cone(position, radius1, radius2, height); - const matrix = new THREE.Matrix4(); - if (flip) { - cone.applyMatrix(matrix.makeRotationX(Math.PI)); - cone.applyMatrix(matrix.makeTranslation(0, position[1] * 2, 0)); - } - cone.applyMatrix(matrix.makeTranslation(0, 0, z_offset)); - return cone; - } - - function TwoPointBoxFeature(start, end, width, height, flip, z_offset) { - const box = TwoPointRoundedBox(start, end, width, height); - const matrix = new THREE.Matrix4(); - - if (flip) { - box.applyMatrix(matrix.makeTranslation(0, 0, -height)); - } - box.applyMatrix(matrix.makeTranslation(0, 0, z_offset)); - return box; - } - - function Channel(channel, layer, z_offset) { - const start = channel.params.start; - const end = channel.params.end; - const width = channel.params.width; - const height = channel.params.height; - const flip = layer.params.flip; - var z_offset = layer.params.z_offset; - const geom = TwoPointBoxFeature(start, end, width, height, flip, z_offset); - const material = getFeatureMaterial(channel, layer); - const mesh = new THREE.Mesh(geom, material); - return mesh; - } - - function Cone(position, radius1, radius2, height) { - const cyl = new THREE.CylinderGeometry(radius2, radius1, height, 16); - const material = redMaterial; - const matrix = new THREE.Matrix4(); - cyl.applyMatrix(matrix.makeRotationX(Math.PI / 2)); - cyl.applyMatrix(matrix.makeTranslation(position[0], position[1], height / 2)); - return cyl; - } - - function TwoPointBox(start, end, width, height) { - const dX = end[0] - start[0]; - const dY = end[1] - start[1]; - const boxAngle = Math.atan2(dY, dX); - const dXPow = Math.pow(dX, 2); - const dYPow = Math.pow(dY, 2); - const length = Math.sqrt(dXPow + dYPow); - const material = blueMaterial; - const box = new THREE.BoxGeometry(length, width, height); - const matrix = new THREE.Matrix4(); - box.applyMatrix(matrix.makeRotationZ(boxAngle)); - box.applyMatrix(matrix.makeTranslation(start[0], start[1], height / 2)); - box.applyMatrix(matrix.makeTranslation(dX / 2, dY / 2, 0)); - return box; - } - - function Slide(width, height, thickness) { - const group = new THREE.Group(); - const slide = new THREE.BoxGeometry(width, height, thickness); - const material = slideMaterial; - const matrix = new THREE.Matrix4(); - slide.applyMatrix(matrix.makeTranslation(width / 2, height / 2, -thickness / 2)); - const mesh = new THREE.Mesh(slide, material); - group.add(mesh); - group.add(DevicePlane(width, height, thickness + 0.001)); - return group; - } - - function SlideHolder(width, height, thickness, slide) { - const renderedHolder = new THREE.Group(); - if (slide) { - renderedHolder.add(Slide(width, height, thickness)); - } - return renderedHolder; - } - - function TwoPointRoundedBox(start, end, width, height) { - const box = TwoPointBox(start, end, width, height); - const cone1 = Cone(start, width / 2, width / 2, height); - const cone2 = Cone(end, width / 2, width / 2, height); - const merged = mergeGeometries([box, cone1, cone2]); - return merged; - } - - function mergeGeometries(geometries) { - const merged = new THREE.Geometry(); - for (let i = 0; i < geometries.length; i++) { - merged.merge(geometries[i]); - } - return merged; - } - - function sanitizeJSON(json) { - sanitizeParams(json.params); - for (let i = 0; i < json.layers.length; i++) { - sanitizeParams(json.layers[i].params, json.params.height); - for (const key in json.layers[i].features) { - sanitizeParams(json.layers[i].features[key].params, json.params.height); - } - } - } - - function sanitizeParams(params, height) { - for (const key in params) { - if (key == "start" || key == "end" || key == "position") { - const pos = params[key]; - params[key] = [pos[0] / 1000, height - pos[1] / 1000]; - } else { - params[key] = params[key] / 1000; - } - } - } - - function computeHeightInPixels(objectHeight, distance) { - const vFOV = (camera.fov * Math.PI) / 180; // - const height = 2 * Math.tan(vFOV / 2) * distance; // visible height - const ratio = objectHeight / height; - const pixels = container.clientHeight * ratio; - return pixels; - } - - function getCameraDistance(objectHeight, pixelHeight) { - const vFOV = (camera.fov * Math.PI) / 180; - const ratio = pixelHeight / container.clientHeight; - const height = objectHeight / ratio; - const distance = height / (2 * Math.tan(vFOV / 2)); - return distance; - } - }, - { "./OrbitControls": 1, "./STLExporter": 2, "./device_json": 3 } - ] - }, - {}, - [4] -); diff --git a/src/App.vue b/src/App.vue deleted file mode 100644 index 355a12a5..00000000 --- a/src/App.vue +++ /dev/null @@ -1,35 +0,0 @@ - - - - - diff --git a/src/app/core/component.ts b/src/app/core/component.ts deleted file mode 100644 index 4b6677f4..00000000 --- a/src/app/core/component.ts +++ /dev/null @@ -1,584 +0,0 @@ -import Params from "./params"; -import CustomComponent from "./customComponent"; -import ComponentPort from "./componentPort"; -import * as FeatureRenderer2D from "../view/render2D/featureRenderer2D"; -import Port from "../library/port"; -import { ComponentPortInterchangeV1, ComponentInterchangeV1, Point } from "./init"; -import ComponentUtils from "../utils/componentUtils"; -import { ComponentAPI } from "@/componentAPI"; -import MapUtils from "../utils/mapUtils"; - -/** - * This class contains the component abstraction used in the interchange format and the - * high level device model of the microfluidic. - */ -export default class Component { - protected _params: Params; - protected _name: string; - protected _id: string; - protected _entity: string; - protected _featureIDs: Array; - protected _bounds: paper.Rectangle | null; - protected _placed: boolean; - protected _ports: Map; - protected _componentPortTRenders: Map; - protected _xspan: number; - protected _yspan: number; - - protected _renderOffset: Point; - /** - * Default Constructor - * @param {string} type - * @param {Params} params - * @param {String} name - * @param {string} mint - * @param {String} id - */ - constructor(params: Params, name: string, mint: string, id: string = ComponentAPI.generateID()) { - this._params = params; - this._name = name; - this._id = id; - this._entity = mint; - // This stores the features that are a part of the component - this._featureIDs = []; - // TODO: Need to figure out how to effectively search through these - this._bounds = null; - this._placed = false; - this._ports = new Map(); - this._componentPortTRenders = new Map(); - - // TODO - Figure out how to use this for generic components - this._xspan = 0; - this._yspan = 0; - this._renderOffset = [0, 0]; - - // Create and set the ports here itself - - const cleanparamdata = this._params.toMap(); - if ((mint !== "" && mint !== "TEXT") || mint === null) { - const ports = ComponentAPI.getComponentPorts(cleanparamdata, mint); - if (ports != undefined && ports.length >= 0 && ports !== null) { - for (const port of ports) { - this.setPort(port.label, port); - } - } - } else { - console.warn("Component mint is empty"); - } - } - - /** - * Returns the mint type of the component - * - * @readonly - * @type {string} - * @memberof Component - */ - get mint(): string { - return this._entity; - } - - /** - * Returns the offset value of the component - * @type {[number, number]} - * @memberof Component - */ - get offset(): [number, number] { - return this._renderOffset; - } - - /** - * Gets the ports of the component - * @returns {Map()} Returns ports of the component - * @memberof Component - */ - get ports(): Map { - return this._ports; - } - - /** - * Sets the port of the component - * @param {} value - * @returns {void} - * @memberof Component - */ - set ports(value) { - this._ports = value; - } - - /** - * Gets the place of the component - * @returns {Boolean} Returns the place of the component - * @memberof Component - */ - get placed(): boolean { - return this._placed; - } - - /** - * Sets the place - * @param {Boolean} value - * @returns {void} - * @memberof Component - */ - set placed(value: boolean) { - this._placed = value; - } - - /** - * Returns an array of strings that are the feature ids of the component - * @return {Array} Returns an array with the features - * @memberof Component - */ - get featureIDs(): Array { - return this._featureIDs; - } - - /** - * Sets the bounds i.e. the x,y position and the width and length of the component - * @param {Object} bounds PaperJS Rectangle object associated with a Path.bounds property - * @memberof Component - * @returns {void} - */ - setBounds(bounds: paper.Rectangle): void { - this._bounds = bounds; - const topleftpt = bounds.topLeft; - this._params.updateParameter("position", [topleftpt.x, topleftpt.y]); - this._params.updateParameter("xspan", bounds.width); - this._params.updateParameter("yspan", bounds.height); - } - - /** - * Updates the parameters stored by the component - * @param {String} key Key to identify the parameter - * @param {} value New value to be assign in the feature - * @memberof Component - * @returns {void} - */ - updateParameter(key: string, value: any): void { - if (key == "position") console.error("Use updateComponentPosition instead of updateParameter when changing position"); - this._params.updateParameter(key, value); - for (const featureid of this._featureIDs) { - - // Get the feature id and modify it - const feature = ComponentUtils.getFeatureFromID(featureid); - feature.updateParameter(key, value); - } - - // Update component position - const featPos = ComponentUtils.getFeatureFromID(this._featureIDs[0]).getValue("position"); - // Update position (top-left corner) - this.setPosition(); - // Update offset - this.setOffset(); - // Update the ComponentPorts - this.updateComponentPorts(); - } - - /** - * Generates the object that needs to be serialzed into JSON for interchange format V1 - * @returns {ComponentInterchangeV1} Object - * @memberof Component - */ - toInterchangeV1(): ComponentInterchangeV1 { - const bounds = this.getBoundingRectangle(); - - const portdata: Array = []; - const map: Map = this.ports; - if (map !== null) { - for (const key of map.keys()) { - let part: ComponentPort | undefined = map.get(key); - if (part != undefined) { - let p = part.toInterchangeV1(); - portdata.push(p); - } - } - } - - const output: ComponentInterchangeV1 = { - id: this._id, - name: this._name, - entity: this._entity, - params: this._params.toJSON(), - "x-span": this._xspan, - "y-span": this._yspan, - ports: portdata, - layers: this.findLayerReferences() - }; - - return output; - } - - private findLayerReferences(): Array { - const layers = ComponentUtils.getDeviceLayers(); - const layerrefs = []; - let layer; - for (const layer of layers) { - // Check if the component is in layer then put it there - let feature; - for (const key in layer.features) { - feature = layer.features[key]; - if (feature.referenceID == this.id) { - layerrefs.push(layer.id); - } - } - } - return layerrefs; - } - - /** - * Returns the ID of the component - * @returns {string} - * @memberof Component - */ - get id() { - return this._id; - } - - /** - * Allows the user to set the name of the component - * @param {string} name - * @returns {void} - * @memberof Component - * - */ - set name(name: string) { - this._name = name; - } - - /** - * Returns the name of the component - * @returns {string} - * @memberof Component - */ - get name() { - return this._name; - } - - /** - * Returns an Array of size two containing the X and Y coordinates - * @return {Point} - * @memberof Component - */ - getPosition(): Point { - return this._params.getValue("position"); - } - - /** - * Returns the value of the parameter stored against the following key in the component params - * @param {string} key Key to access the value - * @returns {*} Returns the value or an error - * @memberof Component - */ - getValue(key: string): any { - try { - return this._params.getValue(key); - } catch (err) { - throw new Error("Unable to get value for key: " + key); - } - } - - /** - * Adds a feature that is associated with the component - * @param {String} featureID String id of the feature - * @memberof Component - * @returns {void} - */ - addFeatureID(featureID: string): void { - this._featureIDs.push(featureID); - // Now update bounds - // this.__updateBounds(); - } - - /** - * This method updates the bounds of the component - * @private - * @memberof Component - * @returns {void} - */ - private updateBounds(): void { - let bounds = null; - let feature = null; - let renderedfeature = null; - for (const featureid of this._featureIDs) { - // gets teh feature defined by the id - feature = ComponentUtils.getFeatureFromID(featureid); - renderedfeature = FeatureRenderer2D.renderFeature(feature, null); - if (bounds === null) { - bounds = renderedfeature.bounds; - } else { - bounds = bounds.unite(renderedfeature.bounds); - } - } - this._bounds = bounds; - } - - /** - * Gets the params associated with the component - * @return {Params} Returns the params associated with the component - * @memberof Component - */ - get params(): Params { - return this._params; - } - - /** - * Returns a paper.Rectangle object that defines the bounds of the component - * @return {Object} - * @memberof Component - */ - getBoundingRectangle(): paper.Rectangle { - if (this._featureIDs.length == 0 || this._featureIDs === null || this._featureIDs == undefined) { - console.error("No features associated with the component"); - } - let bounds = null; - for (const featureid of this._featureIDs) { - const render = ComponentUtils.getRenderedFeature(featureid); - if (bounds && render) { - bounds = bounds.unite(render.bounds); - } else { - bounds = render.bounds; - } - } - if (bounds !== null) return bounds; - else throw new Error("Component " + this._name + " " + this._id + " cannot have bounds of null"); - } - - /** - * Updates the coordinates of the component and all the connected features - * based on the position from which the features are drawn - * @param {Point} center - * @memberof Component - * @returns {void} - */ - updateComponentPosition(center: Point): void { - console.log("input position: ", center); - // Update component - this._params.updateParameter("position", [center[0] + this._renderOffset[0], center[1] + this._renderOffset[1]]); - // Update features - for (const featureidtochange of this._featureIDs) { - - const feature = ComponentUtils.getFeatureFromID(featureidtochange); - feature.updateParameter("position", center); - } - // Update the ComponentPorts - this.updateComponentPorts(); - } - - setInitialOffset(): void { - const rect = this.getBoundingRectangle(); - this._renderOffset = [rect.x, rect.y]; - } - - setOffset():void { - const rect = this.getBoundingRectangle(); - const featPos = ComponentUtils.getFeatureFromID(this._featureIDs[0]).getValue("position"); - this._renderOffset = [rect.x - featPos[0], rect.y - featPos[1]]; - } - - setPosition():void { - this._params.updateParameter("position", this.getTopLeftPosition()); - } - - - /** - * Replicates the component at the given positions - * @param {Number} xpos Integer location of X - * @param {Number} ypos Integer location of Y - * @param {string} name Name of the replicated component - * @return {Component} - * @memberof Component - */ - replicate(xpos: number, ypos: number, name: string = ComponentUtils.generateDeviceName(this._entity)): Component { - // TODO: Fix this ridiculous chain of converting params back and forth, there should be an easier way - // Converting all the params into raw values - // let paramvalues = {}; - // for(let key in this._params.parameters){ - // paramvalues[key] = this.getValue(key); - // } - - const definition = ComponentAPI.getDefinitionForMINT(this._entity); - if (definition === null) { - throw new Error("Unable to find definition for component type: " + this._entity); - } - // Clean Param Data - const cleanparamdata = this._params.parameters; - const unique_map = MapUtils.toMap(definition.unique); - const heritable_map = MapUtils.toMap(definition.heritable); - const replicaparams = new Params(cleanparamdata, unique_map, heritable_map); - const ret = new Component(replicaparams, name, this._entity); - console.log("Checking what the new component params are:", ret._params); - // Generate New features - for (const featureid of this._featureIDs) { - const feature = ComponentUtils.getFeatureFromID(featureid); - const replica = feature.replicate(this.getPosition()[0], this.getPosition()[1]); - replica.referenceID = ret.id; - ret.featureIDs.push(replica.ID); - - // TODO: add new feature to the layer in which the current feature is in - const currentlayer = ComponentUtils.getDeviceLayerFromID(featureid); - currentlayer.addFeature(replica); - } - console.warn("TODO: Generate renders for the new Features for this new component"); - ret.updateComponentPosition([xpos, ypos]); - return ret; - } - - /** - * Returns the center position of the component as a 2D vector - * @return {Array} - * @memberof Component - */ - getCenterPosition(): Point { - const bounds = this.getBoundingRectangle(); - return [bounds.center.x, bounds.center.y]; - } - - /** - * Returns the topleft position of the component as a 2D vector - * @return {Array} - * @memberof Component - */ - getTopLeftPosition(): Point { - const bounds = this.getBoundingRectangle(); - return [bounds.topLeft.x, bounds.topLeft.y]; - } - - /** - * This method is used to import the component from Interchange V1 JSON - * @param {} json - * @returns {*} - * @memberof component - */ - static fromInterchangeV1(json: ComponentInterchangeV1): Component { - // let set; - // if (json.hasOwnProperty("set")) set = json.set; - // else set = "Basic"; - // //TODO: This will have to change soon when the thing is updated - // throw new Error("Need to implement Interchange V1 Import for component object"); - const iscustomcompnent = false; - const name = json.name; - const id = json.id; - const entity = json.entity; - - // Idk whether this is correct - // It was originially this._span = this.span which threw several errors so I patterned in off the above const var - const xspan = json["x-span"]; - const yspan = json["y-span"]; - - const params = json.params; - - // TODO - remove this dependency - // iscustomcompnent = Registry.viewManager.customComponentManager.hasDefinition(entity); - - let definition; - - if (iscustomcompnent) { - definition = CustomComponent.defaultParameterDefinitions(); - } else { - definition = ComponentAPI.getDefinitionForMINT(entity); - } - - if (definition === null) { - throw Error("Could not find definition for type: " + entity); - } - - let type; - let value; - for (const key in json.params) { - if (Object.prototype.hasOwnProperty.call(definition.heritable, key)) { - type = definition.heritable[key]; - } else if (Object.prototype.hasOwnProperty.call(definition.unique, key)) { - type = definition.unique[key]; - } - // let paramobject = Parameter.generateComponentParameter(key, json.params[key]); - // Check if the value type is float and convert the value from string - value = json.params[key]; - if (type === "Float" && typeof value === "string") { - value = parseFloat(value); - } - - // let paramobject = new Parameter(type, value); - params[key] = value; - } - - // Do another check and see if position is present or not - if (!Object.prototype.hasOwnProperty.call(params, "position")) { - params.position = [0.0, 0.0]; - } - const unique_map = MapUtils.toMap(definition.unique); - const heritable_map = MapUtils.toMap(definition.heritable); - const paramstoadd = new Params(params, unique_map, heritable_map); - const component = new Component(paramstoadd, name, entity, id); - - // Deserialize the component ports - const portdata = new Map(); - for (const port of json.ports) { - const componentport = ComponentPort.fromInterchangeV1(port); - portdata.set(componentport.label, componentport); - } - - component.ports = portdata; - - return component; - } - - /** - * Set port for the component - * @param {string} label - * @param {Port} port - * @memberof Component - * @returns {void} - */ - setPort(label: string, port: ComponentPort): void { - this._ports.set(label, port); - } - - /** - * Gets the rotation of the component - * @returns {Number} Returns the degree of rotation - * @memberof Component - */ - getRotation(): number { - if (this._params.hasParam("rotation")) { - return this.getValue("rotation"); - } else if (this._params.hasParam("orientation")) { - const orientation = this.getValue("orientation"); - if (orientation === "V") { - return 0; - } else { - return 270; - } - } else { - console.warn("Returning rotation = 0 since no rotation was found for component: ", this); - return 0; - } - } - - /** - * - * @param {string} label - * @param {any} render - * @returns {void} - * @memberof Component - */ - attachComponentPortRender(label: string, render: any): void { - this._componentPortTRenders.set(label, render); - } - - /** - * Updates the Component Ports to have the latest location information - * @memberof Component - * @returns {void} - */ - updateComponentPorts(): void { - // updating the Component Ports - const cleanparamdata = this.params.toMap(); - const currPos: [number, number] = cleanparamdata.get("position"); - cleanparamdata.set("position", [currPos[0] - this._renderOffset[0], currPos[1] - this._renderOffset[1]]); - const ports = ComponentAPI.getComponentPorts(cleanparamdata, this._entity); - for (const port of ports) { - this.setPort(port.label, port); - } - } -} diff --git a/src/app/core/componentPort.ts b/src/app/core/componentPort.ts deleted file mode 100644 index 420220fb..00000000 --- a/src/app/core/componentPort.ts +++ /dev/null @@ -1,169 +0,0 @@ -import uuid from "node-uuid"; -import paper from "paper"; -import Component from "./component"; -import { ComponentPortInterchangeV1, LogicalLayerType, Point } from "./init"; - -export default class ComponentPort { - protected _id: string; - protected _x: number; - protected _y: number; - protected _label: string; - protected _layer: LogicalLayerType; - - /** - * Default constructor for ComponentPorts - * @param {Number} x X coordinate - * @param {Number} y Y coordinate - * @param {String} label Name of the component - * @param {string} layer - */ - constructor(x: number, y: number, label: string, layer: LogicalLayerType) { - this._id = uuid.v1(); - this._x = x; - this._y = y; - this._label = label; - this._layer = layer; - } - - /** - * Gets the layer of the component port - * @returns {string} Returns layer - * @memberof ComponentPort - */ - get layer() { - return this._layer; - } - - /** - * Sets the layer - * @param {string} value Value of the layer - * @memberof ComponentPort - * @returns {void} - */ - set layer(value) { - this._layer = value; - } - - /** - * Gets the label - * @returns {string} Returns the label of the component port - * @memberof ComponentPort - */ - get label() { - return this._label; - } - - /** - * Sets the label of the component port - * @param {string} value Label - * @memberof ComponentPort - * @returns {void} - */ - set label(value) { - this._label = value; - } - - /** - * Gets the Y coordinate of the component port - * @returns {number} Returns the y coordinate - * @memberof ComponentPort - */ - get y() { - return this._y; - } - - /** - * Sets the Y coordinate of the component port - * @param {number} y Value of the Y coordinate - * @memberof ComponentPort - * @returns {void} - */ - set y(value) { - this._y = value; - } - - /** - * Gets the X coordinate of the component port - * @returns {number} Returns the X coordinate - * @memberof ComponentPort - */ - get x() { - return this._x; - } - - /** - * Sets the X coordinate of the component port - * @param {number} value Value of the X coordinate - * @returns {void} - * @memberof ComponentPort - */ - set x(value) { - this._x = value; - } - - /** - * Gets the ID of the component port - * @returns {string} Returns the ID - * @memberof ComponentPort - */ - get id() { - return this._id; - } - - /** - * Set the ID of the component port - * @param {string} value ID - * @memberof ComponentPort - * @returns {void} - */ - set id(value) { - this._id = value; - } - - /** - * Converts to Interchange V1 format - * @returns {Object} Returns a object with Interchange V1 format - * @memberof ComponentPort - */ - toInterchangeV1(): ComponentPortInterchangeV1 { - return { - x: this._x, - y: this._y, - layer: this._layer, - label: this._label - }; - } - - /** - * Returns the absolute postition of the component - * @param {Object} componentport Component port object - * @param {Object} component Component object - * @returns {Array} Returns an array which contains the X absolute coordinate and the y absolute coordinate - * @memberof ComponentPort - */ - static calculateAbsolutePosition(componentport: ComponentPort, component: Component): Point { - const topleftposition = component.getValue("position"); - const point = new paper.Point(topleftposition[0] - component.offset[0] + componentport.x, topleftposition[1] - component.offset[1] + componentport.y); - const featpoint = new paper.Point(topleftposition[0] - component.offset[0], topleftposition[1] - component.offset[1]); - const rotatedpoint = point.rotate(component.getRotation(), featpoint); - return [rotatedpoint.x, rotatedpoint.y]; - } - - /** - * Creates a new Component Port from an Interchange V1 format - * @param {} json - * @returns {ComponentPort} Returns a component port object - * @memberof ComponentPort - */ - static fromInterchangeV1(json: ComponentPortInterchangeV1): ComponentPort { - let layer = LogicalLayerType.FLOW; - if(json.layer === "FLOW"){ - layer = LogicalLayerType.FLOW; - } else if (json.layer === "CONTROL"){ - layer = LogicalLayerType.CONTROL; - } else if (json.layer === "INTEGRATION"){ - layer = LogicalLayerType.INTEGRATION; - } - return new ComponentPort(json.x, json.y, json.label, layer); - } -} diff --git a/src/app/core/connection.ts b/src/app/core/connection.ts deleted file mode 100644 index 32b801ff..00000000 --- a/src/app/core/connection.ts +++ /dev/null @@ -1,712 +0,0 @@ -import paper from "paper"; -import Parameter from "./parameter"; -import Params from "./params"; -import ConnectionTarget from "./connectionTarget"; -import Device from "./device"; -import * as FeatureRenderer2D from "../view/render2D/featureRenderer2D"; -import Layer from "./layer"; -import uuid from "node-uuid"; -import { ConnectionInterchangeV1_2, ConnectionPathInterchangeV1_2, ConnectionTargetInterchangeV1 } from "./init"; -import { Segment, Point } from "./init"; -import ConnectionUtils from "../utils/connectionUtils"; -import { ComponentAPI } from "@/componentAPI"; -import MapUtils from "../utils/mapUtils"; -import ExportUtils from "../utils/exportUtils"; -import Feature from "./feature"; - -/** - * This class contains the connection abstraction used in the interchange format and the - * high level device model of the microfluidic. - */ -export default class Connection { - protected _params: Params; - protected _name: string; - protected _id: string; - protected _type: string; - protected _entity: string; - protected _featureIDs: Array; - protected _nodes: any; - protected _bounds: paper.Rectangle | null; - protected _source: ConnectionTarget | null; - protected _sinks: Array; - protected _paths: Array>; - protected _objects: any; - protected _routed: boolean; - protected _layer: Layer; - - features: Array = []; - - /** - * Default Connection Constructor - * @param {String} type - * @param {Params} params - * @param {String} name - * @param {String} mint - * @param {String} id - */ - constructor(type: string, params: Params, name: string, mint: string, layer: Layer, id: string = ComponentAPI.generateID()) { - this._params = params; - this._name = name; - this._id = id; - this._type = type; - this._entity = mint; - //This stores the features that are a part of the component - this._featureIDs = []; - this._nodes = []; - //TODO: Need to figure out how to effectively search through these - this._bounds = null; - this._source = null; - this._sinks = []; - this._paths = []; - this._objects = []; - this._routed = false; - this._layer = layer; - } - - get layer(): Layer { - return this._layer; - } - - set layer(layer: Layer) { - this._layer = layer; - } - /** - * Gets the sinks in the connection - * @returns {ConnectionTarget[]} Returns an array with the sinks - * @memberof Connection - */ - get sinks(): Array { - return this._sinks; - } - - /** - * Gets the source of the connection - * @returns {ConnectionTarget} Returns the source of the connection - * @memberof Connection - */ - get source(): ConnectionTarget | null { - return this._source; - } - - /** - * Checks if the connection is routed - * @returns {Boolean} Returns true whether if it is routed or not - * @memberof Connection - */ - get routed(): boolean { - return this._routed; - } - - /** - * Sets if the connection is routed - * @param {Boolean} value true if it's router or false if it's not - * @returns {void} - * @memberof Connection - */ - set routed(value: boolean) { - this._routed = value; - } - - /** - * Returns the list of features associated with the connection - * @return {Feature[]} - * @memberof Connection - */ - get featureIDs(): Array { - return this._featureIDs; - } - - /** - * Returns the params associated with the connection - * @return {Params} - * @memberof Connection - */ - get params(): Params { - return this._params; - } - - - /** - * Sets the bounds i.e. the x,y position and the width and length of the component - * @param {paper.Rectangle} bounds PaperJS Rectangle object associated with a Path.bounds property - * @memberof Connection - * @returns {void} - */ - setBounds(bounds: paper.Rectangle): void { - this._bounds = bounds; - let topleftpt = bounds.topLeft; - this._params.updateParameter("position", [topleftpt.x, topleftpt.y]); - this._params.updateParameter("xspan", bounds.width); - this._params.updateParameter("yspan", bounds.height); - } - - /** - * Updates the parameters stored by the component - * @param {String} key Identifier of the parameter - * @param {any} value - * @memberof Connection - * @returns {void} - */ - updateParameter(key: string, value: any): void { - this._params.updateParameter(key, value); - - console.log("Key: ", key, " Val: ", value); - - if (key != "segments") { - for (const featureidtochange of this._featureIDs) { - - // Get the feature id and modify it - const feature = ConnectionUtils.getFeatureFromID(featureidtochange); - feature.updateParameter(key, value); - } - } - - // this._params[key] = value; - // this.updateView(); - } - - /** - * Generates the object that needs to be serialzed into JSON for interchange format V1 - * @returns {ConnectionInterchangeV1_2} Object - * @memberof Connection - */ - toInterchangeV1(): ConnectionInterchangeV1_2 { - if (this._source === null) { - throw new Error("Source is null, cannot convert connection to interchange format:" + this._id); - } - const outputpaths: Array = []; - for (let i = 0; i < this._paths.length; i++) { - const path = this._paths[i]; - const outputpath: ConnectionPathInterchangeV1_2 = { - source: this._source !== null ? this._source.toJSON() : null, - sink: this.sinks.length > i ? this._sinks[i].toJSON() : null, - wayPoints: path, - // Get the id's of the features - features: this.features.map(feature => {return feature.id;}) - }; - outputpaths.push(outputpath); - } - const output: ConnectionInterchangeV1_2 = { - id: this._id, - name: this._name, - entity: this._entity, - source: this._source.toJSON(), - sinks: [], - paths: outputpaths, - params: this._params.toJSON(), - layer: this._layer.id - }; - - if (this._source !== null) { - output.source = this._source.toJSON(); - } - if (this._sinks !== null && this._sinks.length > 0) { - let sinks = []; - for (const sink of this._sinks) { - sinks.push(sink.toJSON()); - } - output.sinks = this._sinks.map(sink => { - return ExportUtils.toConnectionTargetInterchangeV1(sink); - }); - } - return output; - } - - /** - * Returns the ID of the component - * @returns {String} - * @memberof Connection - */ - get id(): string { - return this._id; - } - - /** - * Allows the user to set the name of the component - * @param {String} name Name of the component - * @memberof Connection - * @returns {void} - */ - set name(name: string) { - this._name = name; - } - - /** - * Returns the name of the component - * @returns {String} Name of the component - * @memberof Connection - */ - get name(): string { - return this._name; - } - - /** - * Gets the 3DuF Type of the component, this will soon be depreciated and merged with - * the MINT references - * @returns {String} - * @memberof Connection - */ - get type(): string { - return this._type; - } - - /** - * Returns the position of the component - * @return {string} - * @memberof Connection - */ - /** - * Returns the value of the parameter stored against the following key in teh component params - * @returns {any} - * @memberof Connection - */ - getValue(key: string): any { - try { - return this._params.getValue(key); - } catch (err) { - throw new Error("Unable to get value for key: " + key); - } - } - - /** - * Adds a feature that is associated with the component - * @param {String} featureID String id of the feature - * @memberof Connection - * @returns {void} - */ - addFeatureID(featureID: string): void { - this._featureIDs.push(featureID); - //Now update bounds - // this.__updateBounds(); - } - - /** - * This method updates the bounds of the component - * @memberof Connection - * @returns {void} - * @protected - */ - protected updateBounds(): void { - console.log("test"); - let bounds = null; - let feature = null; - let renderedfeature = null; - for (const featureid of this._featureIDs) { - // gets teh feature defined by the id - feature = ConnectionUtils.getFeatureFromID(featureid); - console.log(feature); - renderedfeature = FeatureRenderer2D.renderFeature(feature, null); - console.log("rendered:"); - console.log(renderedfeature); - if (bounds === null) { - bounds = renderedfeature.bounds; - } else { - bounds = bounds.unite(renderedfeature.bounds); - } - } - this._bounds = bounds; - } - - /** - * Sets the params associated with the component - * @param {Params} params key -> Parameter Set - * @returns {void} - * @memberof Connection - */ - set params(params: Params) { - this._params = params; - //TODO: Modify all the associated Features - for (let key in params) { - let value = params.getValue(key); - for (const featureidtochange of this._featureIDs) { - - //Get the feature id and modify it - let feature = ConnectionUtils.getFeatureFromID(featureidtochange); - feature.updateParameter(key, value.getValue()); - } - } - } - - /** - * Returns the list of waypoints associated with the connection - * @return {Point[]} - * @memberof Connection - */ - getPaths(): Array> { - return this._paths; - } - - /** - * Updates the segments of the connection - * @param {Segment[]} segments - * @memberof Connection - * @returns {void} - */ - updateSegments(segments: Array): void { - this.updateParameter("segments", new Parameter("SegmentArray", segments)); - for (const featureidtochange of this._featureIDs) { - - const feature = ConnectionUtils.getFeatureFromID(featureidtochange); - // feature.updateParameter('position', center); - feature.updateParameter("segments", segments); - } - } - - /** - * Inserts the gap using the boundingbox - * @param {any} boundingbox - * @memberof Connection - * @returns {boolean} - */ - insertFeatureGap(boundingbox: any): boolean { - let foundflag = false; - // Convert Rectangle to Path.Rectangle - console.log(boundingbox, boundingbox.width, boundingbox.height); - boundingbox = new paper.Path.Rectangle(boundingbox); - // Check which segment I need to break - const segments = this.getValue("segments"); - for (const i in segments) { - const segment = segments[i]; - const line = new paper.Path.Line(new paper.Point(segment[0]), new paper.Point(segment[1])); - const intersections = line.getIntersections(boundingbox); - // console.log("Intersections found", intersections); - if (intersections.length === 2) { - const break1 = intersections[0].point; - const break2 = intersections[1].point; - const newsegs = this.breakSegment(segment, break1, break2); - console.log("breaking:", segment, newsegs); - if (newsegs.length !== 2) { - throw new Error("Could not break the segments correctly"); - } - segments.splice(i, 1, newsegs[0], newsegs[1]); - foundflag = true; - } else if (intersections.length === 1) { - console.error("Only found 1 intersection point so going to use a different method"); - console.log("Found Intersection:", intersections); - - console.log("Segments:", segments); - console.log("line:", line); - console.log("Bounding Box:", boundingbox); - } else { - console.error("No intersections found so going to use a different method"); - console.log("Found Intersection:", intersections); - - console.log("Segments:", segments); - console.log("line:", line); - console.log("Bounding Box:", boundingbox); - } - } - - // Now that we exit the check for every segment we can verify if this is ok - if (!foundflag) { - console.error("There's something funky going on with the intersection,no intersections found"); - console.log("Segments:", segments); - // console.log("line:", line); - console.log("Bounding Box:", boundingbox); - throw new Error("Could not find 2 intersection points, hence aborting the whole thing"); - } - // console.log("raw new segments:", segments); - this.updateSegments(segments); - - return foundflag; - } - - /** - * Breaks the segment at the 2 points given by the points - * @param {Point[]} segment - * @param {paper.Point} break1 - * @param {paper.Point} break2 - * @return {Segment[]} Returns the two segments - * @memberof Connection - * @protected - */ - protected breakSegment(segment: Segment, break1: paper.Point, break2: paper.Point): Array { - //Generate 2 segments from this 1 segemnt - const p1 = new paper.Point(segment[0]); - const p2 = new paper.Point(segment[1]); - - let segment1: Segment, segment2: Segment; - const p1_break1 = p1.getDistance(break1); - const p2_break1 = p2.getDistance(break1); - const p1_break2 = p1.getDistance(break2); - const p2_break2 = p2.getDistance(break2); - - // Find out if break1 is closer to p1 or p2 - if (p1_break1 + p2_break2 < p2_break1 + p1_break2) { - // break1 is closer to p1 and break2 is closer to p2\ - segment1 = [ - [Math.round(p1.x), Math.round(p1.y)], - [Math.round(break1.x), Math.round(break1.y)] - ]; - segment2 = [ - [Math.round(p2.x), Math.round(p2.y)], - [Math.round(break2.x), Math.round(break2.y)] - ]; - } else { - // break1 is closer to p2 and break1 is closer to p1 - segment1 = [ - [Math.round(p2.x), Math.round(p2.y)], - [Math.round(break1.x), Math.round(break1.y)] - ]; - segment2 = [ - [Math.round(p1.x), Math.round(p1.y)], - [Math.round(break2.x), Math.round(break2.y)] - ]; - } - return [segment1, segment2]; - } - - /** - * This method is used to import the component from Interchange V1 JSON - * @param json - * @returns {Connection} Returns a connection object - * @memberof Connection - */ - static fromInterchangeV1(device: Device, json: ConnectionInterchangeV1_2): Connection { - // let set; - // if (json.hasOwnProperty("set")) set = json.set; - // else set = "Basic"; - // //TODO: This will have to change soon when the thing is updated - // throw new Error("Need to implement Interchange V1 Import for component object"); - // //return Device.makeFeature(json.macro, set, json.params, json.name, json.id, json.type); - - const name = json.name; - const id = json.id; - const entity = json.entity; - const params = json.params; - const layer = device.getLayer(json.layer); - if (layer === null) { - throw new Error("Could not find layer with id: " + json.layer); - } - - // Check if the params have the other unique elements necessary otherwise add them as null - if (!Object.prototype.hasOwnProperty.call(params, "start")) { - // Setting this value to origin - params.start = [0, 0]; - } - if (!Object.prototype.hasOwnProperty.call(params, "end")) { - // Setting this value to origin - params.end = [0, 0]; - } - if (!Object.prototype.hasOwnProperty.call(params, "wayPoints")) { - // TODO: setting a single waypoint at origin - params.wayPoints = [ - [0, 0], - [1, 2] - ]; - } - if (!Object.prototype.hasOwnProperty.call(params, "segments")) { - // TODO: Setting a default segment from origin to origin - params.segments = [ - [ - [0, 0], - [0, 0] - ], - [ - [0, 0], - [0, 0] - ] - ]; - } - let definition = ComponentAPI.getDefinition("Connection"); - if (definition === null || definition === undefined) { - throw new Error("Could not find the definition for the Connection"); - } - const paramstoadd = new Params(params, MapUtils.toMap(definition.unique), MapUtils.toMap(definition.heritable)); - - const connection = new Connection(entity, paramstoadd, name, entity, layer, id); - if (Object.prototype.hasOwnProperty.call(json, "source")) { - if (json.source !== null && json.source !== undefined) { - connection.setSourceFromJSON(device, json.source); - } - } - if (Object.prototype.hasOwnProperty.call(json, "sinks")) { - if (json.sinks !== null && json.sinks !== undefined) { - for (const i in json.sinks) { - const sink = json.sinks[i]; - connection.addSinkFromJSON(device, sink); - } - } - } - if (Object.prototype.hasOwnProperty.call(json, "paths")) { - if (json.paths !== null && json.paths !== undefined) { - for (const i in json.paths) { - connection.addWayPoints(json.paths[i].wayPoints); - } - } - } - - return connection; - } - - /** - * Goes through teh waypoints and generates the connection segments - * @return {SegmentArray} - * @memberof Connection - */ - regenerateSegments(): void { - const pathscopy = this.getPaths(); - const ret: Array = []; - let waypointscopy; - for (const j in pathscopy) { - waypointscopy = pathscopy[j]; - for (let i = 0; i < waypointscopy.length - 1; i++) { - const segment: Segment = [waypointscopy[i], waypointscopy[i + 1]]; - ret.push(segment); - } - } - this.updateSegments(ret); - } - - // /** - // * Allows the user to set the source of the connection - // * @param {Object} component - // * @param {ComponentPort} port - // * @memberof Connection - // * @returns {void} - // */ - // setSource(component: string, port: ComponentPort) { - // if (typeof component != "string" && !(component instanceof String)) { - // console.error("The reference object value can only be a string"); - // } - // this._source = new ConnectionTarget(component, port); - // } - - // /** - // * Allows the user to add a sink to the connection - // * @param {string} component - // * @param {ComponentPort} port - // * @memberof Connection - // * @returns {void} - // */ - // addSink(component: string, port: ComponentPort) { - // if (typeof component != "string" || !(component instanceof String)) { - // console.error("The reference object value can only be a string"); - // } - // this._sinks.push(new ConnectionTarget(component, port)); - // } - - /** - * Adds a new connection target to either the source or the sinks of the connection object. Requires the user to pass - * a ConnectionTarget Object or else it will throw an error. - * @param {string} connectiontarget - * @memberof Connection - * @returns {void} - */ - addConnectionTarget(connectiontarget: ConnectionTarget): void { - if (!(connectiontarget instanceof ConnectionTarget) || connectiontarget === null || connectiontarget == undefined) { - console.error("Cannot add non-ConnectionTarget object as source or sink"); - } - - if (this._source === null) { - this._source = connectiontarget; - } else { - //TODO: Check for duplicates - does it matter actually ? - this._sinks.push(connectiontarget); - } - } - - /** - * Tries to delete any connection target reference that uses the said component - * @param {string} componentid Component ID - * @return {boolean} Returns true if any corresponding connection target is found - * @memberof Connection - * - */ - tryDeleteConnectionTarget(componentid: string): boolean { - let ret = false; - - let source = this._source; - if (source !== null) { - if (source.component.id == componentid) { - //Remove the source object - this._source = null; - ret = true; - } - } - - for (let i in this._sinks) { - let sink = this._sinks[i]; - - if (sink.component.id == componentid) { - this._sinks.splice(+i, 1); - ret = true; - } - } - - return ret; - } - - /** - * Adds a new set of waypoints to the path field of the connection - * @param {} wayPoints - * @memberof Connection - * @returns {void} - */ - addWayPoints(wayPoints: Array): void { - this._paths.push(wayPoints); - } - - /** - * Merges connections - * @param {Connection} connection - * @memberof Connection - * @returns {void} - */ - mergeConnection(connection: Connection): void { - console.error("Merge the newly found connection with the new connection"); - // TODO: - /* - 1. Transfer all the paths - 2. Transfer all the ConnectionTargets - 3. Transfer all the other objects - 4. Move the params - 5. - */ - } - - /** - * Converts from JSON format to connection object - * @param {Object} device - * @param {JSON} json - * @memberof Connection - * @returns {void} - */ - setSourceFromJSON(device: Device, json: ConnectionTargetInterchangeV1): void { - const target = ConnectionTarget.fromJSON(device, json); - this._source = target; - } - - /** - * Adds a sink to the connection - * @param {Object} device - * @param {JSON} json - * @memberof Connection - * @returns {void} - */ - addSinkFromJSON(device: Device, json: ConnectionTargetInterchangeV1): void { - let target = ConnectionTarget.fromJSON(device, json); - this._sinks.push(target); - } - - /** - * Adds a feature to the connection - * - * @param {Feature} feature - * @memberof Connection - */ - addFeature(feature: Feature): void { - this.features.push(feature); - } - - /** - * Removes a feature from the connection - * - * @param {Feature} feature - * @memberof Connection - */ - removeFeature(feature: Feature): void { - this.features.splice(this.features.indexOf(feature), 1); - } - -} diff --git a/src/app/core/connectionTarget.ts b/src/app/core/connectionTarget.ts deleted file mode 100644 index 7576a56c..00000000 --- a/src/app/core/connectionTarget.ts +++ /dev/null @@ -1,69 +0,0 @@ -import Component from "./component"; -import Device from "./device"; -import { ConnectionTargetInterchangeV1 } from "./init"; - -/** - * Connection target class - */ -export default class ConnectionTarget { - protected _component: Component; - protected _portLabel: string; - - /** - * Default ConnectionTarget Constructor - * @param {Component} component - * @param {string} portLabel - */ - constructor(component: Component, portLabel: string) { - this._component = component; - this._portLabel = portLabel; - } - - /** - * Gets the port label of the object - * @returns {string} Returns the port label of the object - * @memberof ConnectionTarget - */ - get portLabel(): string { - return this._portLabel; - } - - /** - * Gets the component in the connection - * @returns {Component} Returns a component object - * @memberof ConnectionTarget - */ - get component(): Component { - return this._component; - } - - /** - * Converts to JSON format - * @returns {JSON} - * @memberof ConnectionTarget - */ - toJSON(): { component: string; port: string } { - // This is for the older design data - if (this._component instanceof Component) { - return { - component: this._component.id, - port: this._portLabel - }; - } else { - return { component: this._component, port: this._portLabel }; - } - } - - /** - * Creates a new connection from a JSON format - * @param {Device} device Device in the connection - * @param {JSON} json File where the connection is contain - * @returns {ConnectionTarget} Returns a Connection Target Object - * @memberof ConnectionTarget - */ - static fromJSON(device: Device, json: ConnectionTargetInterchangeV1): ConnectionTarget { - const component = device.getComponentByID(json.component); - if (component !== null) return new ConnectionTarget(component, json.port); - else throw new Error("Component not found"); - } -} diff --git a/src/app/core/customComponent.ts b/src/app/core/customComponent.ts deleted file mode 100644 index 0e618861..00000000 --- a/src/app/core/customComponent.ts +++ /dev/null @@ -1,164 +0,0 @@ -import DXFObject from "./dxfObject"; -import Device from "./device"; - -import Params from "./params"; -import Template from "../library/template"; -import Feature from "./feature"; -import DeviceUtils from "../utils/deviceUtils"; -import { ComponentAPI, LibraryEntryDefinition } from "@/componentAPI"; - -/** - * This class contains the component abstraction used in the interchange format and the - * high level device model of the microfluidic. - */ -export default class CustomComponent extends Template { - dxfData: any = null; - protected _type: string = ""; - protected _entity: string = ""; - protected _renderData: any = null; - protected _params: Params = new Params({}, new Map(), new Map()); - - /** - * Default constructor - * @param {String} type Type of component - * @param {DXFObject} dxfdata DXFObject - * @param {String} mint Unique MINT identifier - */ - constructor(type: string, dxfdata: any, mint: string = type.toUpperCase()) { - super(); - // this.__params = params; - this._type = type; - this._entity = mint; - this.dxfData = dxfdata; - // this.__params = null; - // this.__renderData = null; - // This stores the features that are a part of the component - // this.__features = []; - // //TODO: Need to figure out how to effectively search through these - // this.__bounds = null; - } - - /** - * Returns the entity type - * @return {string} - * @memberof CustomComponent - */ - get entity(): string { - return this._entity; - } - - /** - * Returns the type - * @return {string} - * @memberof CustomComponent - */ - get type(): string { - return this._type; - } - - /** - * Sets the rendering data - * @param {} data - * @memberof CustomComponent - * @returns {void} - */ - set renderData(data: any) { - this._renderData = data; - } - - /** - * Generates a Feature that has all the corresponding respective data - * @returns {Feature} Returns a feature based on the data - * @memberof CustomComponent - */ - generateComponent(): Feature { - const paramvalues = {}; - const feature = Device.makeFeature(this.type, paramvalues, DeviceUtils.generateNewName(this.type), ComponentAPI.generateID(), "XY", this.dxfData); - return feature; - } - - /** - * Generates the object that needs to be serialzed into JSON for interchange format V1 - * @returns {JSON} Object - * @memberof CustomComponent - */ - toJSON() { - const dxfdata = []; - for (const i in this.dxfData) { - dxfdata.push(this.dxfData[i].getData()); - } - - const output = { - type: this.type, - entity: this.entity, - params: this._params.toJSON(), - dxfData: dxfdata - }; - return output; - } - - /** - * This method is used to import the component from Interchange V1 JSON - * @param json - * @returns {CustomComponent} - * @memberof CustomComponent - */ - static fromInterchangeV1(json: any) { - const dxfdata = []; - for (const i in json.dxfData) { - dxfdata.push(new DXFObject(json.dxfData[i])); - } - - // TODO: This will have to change soon when the thing is updated - const ret = new CustomComponent(json.type, dxfdata, json.entity); - // ret.renderData = json.renderData; - // let render = DXFRenderer.renderDXFObjects(dxfdata); - // ret.renderData = render.exportSVG(); - return ret; - } - - /** - * Contains the default parameters - * @returns {Object} Returns an Object containing the default parameters - * @memberof CustomComponent - */ - static defaultParameterDefinitions(): LibraryEntryDefinition { - const params = { - unique: { - position: "Point" - }, - heritable: { - rotation: "Float", - // "x-scale": "Float", - // "width": "Float", - height: "Float" - }, - units: { - rotation: "°", - // "length": "μm", - // "width": "μm", - height: "μm" - }, - defaults: { - rotation: 0, - // "width": 1.23 * 1000, - // "length": 4.92 * 1000, - height: 0.1 * 1000 - }, - minimum: { - rotation: 0, - // "width": 30, - // "length": 120, - height: 1 - }, - maximum: { - rotation: 359, - // "width": 6000, - // "length": 24 * 1000, - height: 1200 - }, - mint: "" - }; - return params; - } -} diff --git a/src/app/core/device.ts b/src/app/core/device.ts deleted file mode 100644 index 864a6895..00000000 --- a/src/app/core/device.ts +++ /dev/null @@ -1,1135 +0,0 @@ -/// - -import Params from "./params"; -import GeometryElement from "./geometryElement"; - -import Feature from "./feature"; -import { DeviceInterchangeV1, DeviceInterchangeV1_1, LogicalLayerType, Point, ValveInterchangeV1_2, ValveType } from "./init"; -import { ComponentInterchangeV1 } from "./init"; -import { ConnectionInterchangeV1_2 } from "./init"; -import { LayerInterchangeV1 } from "./init"; - -import Layer from "./layer"; -import Component from "./component"; -import Connection from "./connection"; -import EdgeFeature from "./edgeFeature"; -import DXFObject from "./dxfObject"; -import ComponentPort from "./componentPort"; -import * as IOUtils from "../utils/ioUtils"; - -import DeviceUtils from "@/app/utils/deviceUtils"; -import { ComponentAPI } from "@/componentAPI"; -import MapUtils from "../utils/mapUtils"; -import { SerializationError } from "../utils/exportUtils"; - -/** - * The Device stores information about a design. - */ -export default class Device { - private __layers: Array; - private __textLayers: Array; - private __params: Params; - private __name: string; - private __components: Array; - private __nameMap: Map; - private __connections: Array; - private __valveMap: Map; - private __valveTypeMap: Map; - private __groups: Array; - private __parchmintFeatures: Array; - - /** - * Default Constructor - * @param {*} values - * @param {string} name Name of the Device - */ - constructor(values: { [index: string]: any }, name: string = "New Device") { - this.__layers = []; - this.__textLayers = []; - //this.__features = []; - this.__groups = []; - this.__params = new Params(values, Device.getUniqueParameters(), Device.getHeritableParameters()); - // this.setXSpan(values.width); - // this.setYSpan(values.length); - - this.__name = name; - this.__components = []; - this.__nameMap = new Map(); - this.__connections = []; - - //Map to store - this.__valveMap = new Map(); - this.__valveTypeMap = new Map(); - - // Initilize the Features array that would be used to store the Parchmint Features - this.__parchmintFeatures = []; - } - - /** - * Adds a layer to the device - * - * @param {string} componentid - * @param {string} connectionid - * @param {ValveType} valvetype - * @memberof Device - */ - addValve(componentid: string, connectionid: string, valvetype: ValveType): void { - this.__valveMap.set(componentid, connectionid); - this.__valveTypeMap.set(componentid, valvetype); - } - - /** - * Returns the name of the device - * - * @returns {String} - * @memberof Device - */ - get name(): string { - return this.__name; - } - - /** - * Sets the map used for naming objects - * @param {Map} - * @memberof Device - */ - set nameMap(nameMap: Map) { - this.__nameMap = nameMap; - } - - /** - * Returns the list of layers in the device - * @return {Array} - * @memberof Device - */ - get layers(): Array { - return this.__layers; - } - - get parchmintFeatures(): Array { - return this.__parchmintFeatures; - } - - /** - * Adds a connection to the device - * @param {Connection} connection - * @memberof Device - * @returns {void} - */ - addConnection(connection: Connection): void { - this.__connections.push(connection); - } - - /** - * Removes a connection from the device - * @param {Connection} connection - * @memberof Device - * @returns {void} - */ - removeConnection(connection: Connection): void { - let i = this.__connections.indexOf(connection); - if (i != -1) { - this.__connections.splice(i, 1); - } - } - - /** - * Adds a component to the device - * @param {Component} component Component to be added to the device - * @memberof Device - * @returns {void} - */ - addComponent(component: Component): void { - if (component instanceof Component) { - this.__components.push(component); - } else { - throw new Error("Tried to add a component that isn't a component to the device"); - } - } - - /** - * Removes a component from the device - * @param {Component} component Component to remove from the device - * @memberof Device - * @returns {void} - */ - removeComponent(component: Component): null | Connection { - //Remove the component from the map - let trydelete; - let componentid = component.id; - let connectiontorefresh = null; - - //Remove component from connections - for (const connection of this.__connections) { - try { - trydelete = connection.tryDeleteConnectionTarget(componentid); - if (trydelete) { - console.log("Removed Component from Connection : ", connection.id); - } - } catch (e) { - console.error(e); - } - } - //Check if the valve map has the component - let checkConnection: string | undefined = this.__valveMap.get(componentid); - if (checkConnection != undefined) { - connectiontorefresh = this.getConnectionByID(checkConnection); - this.__valveMap.delete(componentid); - } - - let i = this.__components.indexOf(component); - if (i != -1) { - this.__components.splice(i, 1); - } - - return connectiontorefresh; - } - - /** - * Returns the list of components from the device - * @return {Array} Array with the components of the device - * @memberof Device - */ - get components(): Array { - return this.__components; - } - - /** - * Sets the name of the device - * @param {string} name Name of the device - * @memberof Device - */ - set name(name: string) { - this.__name = name; - } - - /** - * Updates the parameter - * @param {string} key Key to identigy the parameter - * @param {} value Parameter's value - * @memberof Device - * @returns {void} - */ - updateParameter(key: string, value: any): void { - this.__params.updateParameter(key, value); - } - - /** - * Returns the layer with the given ID - * - * @param {string} id - * @returns {(Layer | null)} - * @memberof Device - */ - getLayer(id: string): Layer | null { - for (let i in this.__layers) { - let layer = this.__layers[i]; - if (layer.id == id) { - return layer; - } - } - return null; - } - - /** - * Returns the layer that contains the feature with the given feature ID - * @param {string} featureID ID of the feature to search for it - * @return {Layer} Returns the layer - * @memberof Device - */ - getLayerFromFeatureID(featureID: string): Layer { - for (let i = 0; i < this.__layers.length; i++) { - let layer = this.__layers[i]; - if (layer.containsFeatureID(featureID)) { - return layer; - } - } - for (let i = 0; i < this.__textLayers.length; i++) { - let layer = this.__textLayers[i]; - if (layer.containsFeatureID(featureID)) { - return layer; - } - } - throw new Error("FeatureID " + featureID + " not found in any layer."); - } - - /** - * Checks if feature with given feature id is part of the device - * @param {string} featureID ID of the feature to search for it - * @return {boolean} - * @memberof Device - */ - containsFeatureID(featureID: string): boolean { - for (let i = 0; i < this.__layers.length; i++) { - if (this.__layers[i].containsFeatureID(featureID)) return true; - } - return false; - } - - /** - * Returns a list of all the features in the device - * @return {Array} Array with all the features of the device - * @memberof Device - */ - getAllFeaturesFromDevice(): Array { - let features: Array = []; - for (let i in this.__layers) { - //features.push.apply(features, layer.features); - let layer: Layer = this.__layers[i]; - for (let j in layer.features) { - // console.log(layer.features[j]); - features.push(layer.getFeature(j)); - } - } - return features; - } - - /** - * Returns the feature with the given feature id - * @param {string} featureID ID of the feature to search - * @return {Feature} - * @memberof Device - */ - getFeatureByID(featureID: string): Feature { - let layer = this.getLayerFromFeatureID(featureID); - return layer.getFeature(featureID); - } - - /** - * Returns the feature with the given name - * @param {string} name Name of the feature to be search - * @return {Feature} - * @memberof Device - */ - getFeatureByName(name: string): Feature { - let layer; - let features; - for (let i = 0; i < this.__layers.length; i++) { - layer = this.__layers[i]; - features = layer.getAllFeaturesFromLayer(); - for (let ii in features) { - let feature = features[ii]; - if (feature.getName() === name) { - return feature; - } - } - } - for (let i = 0; i < this.__textLayers.length; i++) { - layer = this.__layers[i]; - features = layer.getAllFeaturesFromLayer(); - for (let ii in features) { - let feature = features[ii]; - if (feature.getName() === name) { - return feature; - } - } - } - throw new Error("FeatureID " + name + " not found in any layer."); - } - - /** - * Add a layer, and re-sort the layers array - * @param {Layer} layer Layer to add - * @memberof Device - * @returns {void} - */ - addLayer(layer: Layer): void { - layer.device = this; - this.__layers.push(layer); - //this.sortLayers(); - // TODO: Fix layer system - DeviceUtils.addLayer(layer, this.__layers.indexOf(layer)); - } - - /** - * Add a layer to specific index, and re-sort the layers array - * @param {Layer} layer Layer to add - * @param {number} index The index into which to add the layer - * @memberof Device - * @returns {void} - */ - addLayerAtIndex(layer: Layer, index: number): void { - layer.device = this; - this.__layers.splice(index, 0, layer); - //this.sortLayers(); - // TODO: Fix layer system - DeviceUtils.addLayer(layer, this.__layers.indexOf(layer)); - } - - /** - * Removes feature of the Device - * @param {Feature} feature Feature to be removed - * @memberof Device - * @returns {void} - */ - removeFeature(feature: Feature): void { - if (feature.type == "Connection") { - for (let i = 0; i < this.__connections.length; i++) { - let featIDs = this.__connections[i].featureIDs; - for (let j = 0; j < featIDs.length; j++) { - if (this.__connections[i].featureIDs[j] == feature.ID) { - this.__connections[i].featureIDs.splice(j, 1); - if (this.__connections[i].featureIDs.length == 0) { - this.__connections.splice(i, 1); - } - } - } - } - } else { - for (let i = 0; i < this.__components.length; i++) { - let featIDs = this.__components[i].featureIDs; - for (let j = 0; j < featIDs.length; j++) { - if (this.__components[i].featureIDs[j] == feature.ID) { - this.__components[i].featureIDs.splice(j, 1); - if (this.__components[i].featureIDs.length == 0) { - this.__components.splice(i, 1); - } - } - } - } - } - } - - /** - * Gets the unique parameters - * @returns {Object} - */ - static getUniqueParameters(): Map { - let unique: Map = new Map(); - unique.set("x-span", "Float"); - unique.set("y-span", "Float"); - return unique; - } - - /** - * Update the cross-reference - * @param {String} objectID ID of the object to search for - * @param {String} featureID ID of the feature to search in the given object - * @memberof Device - * @returns {void} - */ - updateObjectReference(objectID: string, featureID: string): void { - //Goes through the components to update the reference - let component: Component; - let foundflag = false; - for (const component of this.__components) { - // console.log(objectID, component.id); - if (objectID == component.id) { - component.addFeatureID(featureID); - component.placed = true; - foundflag = true; - } - } - - //Goes through the connection to update the reference - let connection; - for (const connection of this.__connections) { - if (objectID == connection.id) { - connection.addFeatureID(featureID); - connection.routed = true; - foundflag = true; - } - } - - if (!foundflag) { - console.error("Could not find object to update reference: " + featureID); - } - } - /** - * ? - */ - static getHeritableParameters(): Map { - return new Map(); - } - /** - * Converts groups to JSON - * @returns {JSON} - * @memberof Device - */ - __groupsToJSON(): Array { - let output: Array = []; - for (let i in this.__groups) { - output.push(this.__groups[i]); - } - return output; - } - /** - * Converts layers to JSON - * @returns {JSON} - * @memberof Device - */ - __layersToJSON(): Array<{ [index: string]: any }> { - let output: Array<{ [index: string]: any }> = []; - for (let i in this.__layers) { - output.push(this.__layers[i].toJSON()); - } - return output; - } - /** - * Returns an array with the components - * @returns {Array} - * @memberof Device - */ - __componentsToInterchangeV1(errorList: Array): Array { - let output: Array = []; - for (let i in this.__components) { - try { - output.push(this.__components[i].toInterchangeV1()); - } - catch (e) { - console.error(e); - errorList.push(new SerializationError( - e.message, - `Component ${this.__components[i].id} could not be converted to InterchangeV1`, - JSON.stringify(this.__components[i]), - )); - } - } - return output; - } - /** - * Converts connection to InterchangeV1 - * @returns {Array} Returns an array with the connections - * @memberof Device - */ - __connectionToInterchangeV1(errorList: Array): Array { - let output: Array = []; - for (let i in this.__connections) { - try { - output.push(this.__connections[i].toInterchangeV1()); - } catch (e) { - console.error(e); - errorList.push(new SerializationError( - e.message, - `Connection : ${this.__connections[i].id} could not be converted to InterchangeV1`, - JSON.stringify(this.__connections[i]), - )); - } - } - return output; - } - - __valvesToInterchangeV1(errorList: Array): Array { - let output: Array = []; - this.__valveMap.forEach((target, valveID) => { - let valve_type = this.__valveTypeMap.get(valveID); - if(valve_type === undefined) { - console.warn("Valve type not found for valve: " + valveID + " , setting default to NORMALLY_OPEN"); - valve_type = ValveType.NORMALLY_OPEN; - } - try { - output.push({ - componentid: valveID, - connectionid: target, - type: valve_type, - params: {} - }); - } catch (e) { - console.error(e); - errorList.push(new SerializationError( - e.message, - `Valve : ${valveID} could not be converted to InterchangeV1`, - JSON.stringify(valveID), - )); - } - }); - return output; - } - - /** - * Converts feature layers to InterchangeV1 - * @return {Array} Returns an array with the feature layers - * @memberof Device - */ - __featureLayersToInterchangeV1(): Array { - let output: Array = []; - for (let i in this.__layers) { - output.push(this.__layers[i].toInterchangeV1()); - } - return output; - } - /** - * Converts layers to InterchangeV1 - * @return {Array} Returns an array with the layers - * @memberof Device - */ - __layersToInterchangeV1(errorList: Array): Array { - const output: Array = []; - for (const i in this.__layers) { - try { - output.push(this.__layers[i].toInterchangeV1()); - } catch (e) { - console.error(e); - errorList.push(new SerializationError( - e.message, - `Layer ${this.__layers[i].id} could not be converted to InterchangeV1`, - JSON.stringify(this.__layers[i]) - )); - } - } - return output; - } - - /** - * Loads feature layers from a Interchange format into the device object - * @param {*} json - * @memberof Device - * @returns {void} - */ - __loadLayersFromInterchangeV1(json: Array): void { - for (let i in json) { - let newLayer = Layer.fromInterchangeV1(json[i], this); - this.addLayer(newLayer); - } - } - - /** - * Loads the JSON Component object into the device object - * @param {ComponentInterchangeV1} components - * @memberof Device - * @returns {void} - * @private - */ - __loadComponentsFromInterchangeV1(components: Array): void { - let componenttoadd; - - for (let i in components) { - componenttoadd = Component.fromInterchangeV1(components[i]); - this.__components.push(componenttoadd); - } - } - /** - * Loads connections to the device object - * @param {Connection} connections Connections to add to the device - * @memberof Device - * @returns {void} - */ - __loadConnectionsFromInterchangeV1(connections: Array): void { - let connectiontoload; - for (let i in connections) { - connectiontoload = Connection.fromInterchangeV1(this, connections[i]); - this.__connections.push(connectiontoload); - } - } - - /** - * Converts to Interchange V1 format - * @returns {Device} Returns an Device object in Interchange V1 format - * @memberof Device - */ - toInterchangeV1(errorList: Array): DeviceInterchangeV1 { - let output: DeviceInterchangeV1 = { - name: this.__name, - params: { - width: this.getXSpan(), - length: this.getYSpan() - }, - //TODO: Use this to dynamically create enough layers to scroll through - layers: this.__layersToInterchangeV1(errorList), - components: this.__componentsToInterchangeV1(errorList), - connections: this.__connectionToInterchangeV1(errorList), - valves: this.__valvesToInterchangeV1(errorList), - version: "1", - groups: this.__groupsToJSON() - }; - return output; - } - - toInterchangeV1_1(errorList: Array): DeviceInterchangeV1_1 { - let output: DeviceInterchangeV1_1 = { - name: this.__name, - params: { - width: this.getXSpan(), - length: this.getYSpan() - }, - //TODO: Use this to dynamically create enough layers to scroll through - layers: this.__layersToInterchangeV1(errorList), - components: this.__componentsToInterchangeV1(errorList), - connections: this.__connectionToInterchangeV1(errorList), - version: "1.1", - groups: this.__groupsToJSON() - }; - return output; - } - - static fromInterchangeV1(json: DeviceInterchangeV1): Device { - let newDevice: Device; - if (Object.prototype.hasOwnProperty.call(json, "params")) { - if (Object.prototype.hasOwnProperty.call(json.params, "width") && Object.prototype.hasOwnProperty.call(json.params, "length")) { - newDevice = new Device( - { - width: json.params.width, - length: json.params.length - }, - json.name - ); - } else { - newDevice = new Device( - { - width: 135000, - length: 85000 - }, - json.name - ); - } - } else { - console.warn("Could not find device params, using some default values for device size"); - newDevice = new Device( - { - width: 135000, - length: 85000 - }, - json.name - ); - } - //TODO: Use this to dynamically create enough layers to scroll through - //newDevice.__loadLayersFromInterchangeV1(json.layers); - //TODO: Use these two generate a rat's nest - newDevice.__loadComponentsFromInterchangeV1(json.components); - newDevice.__loadConnectionsFromInterchangeV1(json.connections); - //TODO: Use this to render the device features - - //Check if JSON has features else mark - if (Object.prototype.hasOwnProperty.call(json, "layers")) { - newDevice.__loadLayersFromInterchangeV1(json.layers); - } else { - //We need to add a default layer - let newlayer = new Layer({}, "flow", LogicalLayerType.FLOW, "0", newDevice); - newDevice.addLayer(newlayer); - newlayer = new Layer({}, "control", LogicalLayerType.CONTROL, "0", newDevice); - newDevice.addLayer(newlayer); - } - - //Updating cross-references - let features = newDevice.getAllFeaturesFromDevice(); - let feature; - for (let i in features) { - //console.log("Feature:", features[i]); - feature = features[i]; - if (feature.referenceID !== null) { - newDevice.updateObjectReference(feature.referenceID, feature.ID); - } - } - - return newDevice; - } - - static fromInterchangeV1_1(json: DeviceInterchangeV1): Device { - IOUtils.sanitizeV1Plus(json); - let newDevice; - - if (Object.prototype.hasOwnProperty.call(json, "params")) { - if (Object.prototype.hasOwnProperty.call(json.params, "xspan") && Object.prototype.hasOwnProperty.call(json.params, "yspan")) { - newDevice = new Device( - { - width: json.params.xspan, - length: json.params.yspan - }, - json.name - ); - } else { - newDevice = new Device( - { - width: 135000, - length: 85000 - }, - json.name - ); - } - } else { - console.warn("Could not find device params, using some default values for device size"); - newDevice = new Device( - { - width: 135000, - length: 85000 - }, - json.name - ); - } - //TODO: Use this to dynamically create enough layers to scroll through - //newDevice.__loadLayersFromInterchangeV1(json.layers); - //TODO: Use these two generate a rat's nest - newDevice.__loadComponentsFromInterchangeV1(json.components); - newDevice.__loadConnectionsFromInterchangeV1(json.connections); - - let valve_map, valve_type_map; - //Import ValveMap - if (Object.prototype.hasOwnProperty.call(json.params, "valveMap") && Object.prototype.hasOwnProperty.call(json.params, "valveTypeMap")) { - valve_map = IOUtils.jsonToMap(json.params.valveMap); - console.log("Imported valvemap", valve_map); - - console.log("Loaded valvetypemap", json.params.valveTypeMap); - valve_type_map = IOUtils.jsonToMap(json.params.valveTypeMap); - - console.log(json.params.valveTypeMap, valve_type_map); - for (let [componentid, connectionid] of valve_map) { - let valve = newDevice.getComponentByID(componentid); - if(valve === null) { - console.error("Could not find valve with id:", componentid); - throw new Error("Could not find valve with id: " + componentid); - } - let connection = newDevice.getConnectionByID(connectionid); - if(connection === null) { - console.error("Could not find connection with id:", connectionid); - throw new Error("Could not find connection with id: " + connectionid); - } - const valve_type_text = valve_type_map.get(componentid); - let valve_type = ValveType.NORMALLY_OPEN; - if (valve_type_text === "NORMALLY_OPEN") { - valve_type = ValveType.NORMALLY_OPEN; - }else if(valve_type_text === "NORMALLY_CLOSED") { - valve_type = ValveType.NORMALLY_CLOSED; - } else { - console.warn("Could not find valve type for valve with id:", componentid); - throw new Error("Could not find valve type for valve with id: " + componentid); - } - - newDevice.insertValve(valve, connection, valve_type_map.get(componentid)); - } - } - - //TODO: Use this to render the device features - - //Check if JSON has features else mark - if (Object.prototype.hasOwnProperty.call(json, "features")) { - newDevice.__loadLayersFromInterchangeV1(json.layers); - } else { - //We need to add a default layer - let newlayer = new Layer({}, "flow", LogicalLayerType.FLOW, "0", newDevice); - newDevice.addLayer(newlayer); - newlayer = new Layer({}, "control", LogicalLayerType.CONTROL, "0", newDevice); - newDevice.addLayer(newlayer); - } - - //Updating cross-references - let features = newDevice.getAllFeaturesFromDevice(); - let feature; - for (let i in features) { - //console.log("Feature:", features[i]); - feature = features[i]; - if (feature.referenceID !== null) { - newDevice.updateObjectReference(feature.referenceID, feature.ID); - } - } - - return newDevice; - } - - /** - * Set the X-Span Value - * @param {number} value - * @memberof Device - * @returns {void} - */ - setXSpan(value: number): void { - this.__params.updateParameter("x-span", value); - } - - /** - * Set the Y-Span Value - * @param {number} value - * @memberof Device - * @returns {void} - */ - setYSpan(value: number): void { - this.__params.updateParameter("y-span", value); - } - - /** - * Returns the X-Span Value - * @return {number} - * @memberof Device - */ - getXSpan(): number { - return this.__params.getValue("x-span"); - } - - /** - * Returns the Y-Span Value - * @return {number} - * @memberof Device - */ - getYSpan(): number { - return this.__params.getValue("y-span"); - } - - /** - * Create the layers necessary for creating a new level - * @return {Array} Returns a the layer objects created - * @memberof Device - */ - createNewLayerBlock(layers: Array): void { - for (let i in layers) { - this.addLayer(layers[i]); - } - } - - /** - * Deletes the layer defined by the index - * @param {number} index - * @memberof Device - * @returns {void} - */ - deleteLayer(index: number): void { - let layer = this.__layers[index]; - for (let feature in layer.features) { - this.removeFeature(layer.features[feature]); - } - if (index != -1) { - this.__layers.splice(index, 1); - } - } - - /** - * Returns the component identified by the id - * @param {string} id ID of the feature to get the component - * @return {Component|null} - * @memberof Device - */ - getComponentForFeatureID(id: string): Component | null { - for (let i in this.__components) { - let component = this.__components[i]; - //go through each component's features - for (let j in component.featureIDs) { - let featureid = component.featureIDs[j]; - if (featureid === id) { - return component; - } - } - } - - return null; - } - - /** - * Generates a new new name for the type, use this to autogenerate the names for components that are typespecific - * @param {string} type - * @return {string} - * @memberof Device - */ - generateNewName(type: string): string { - let value: number | undefined = this.__nameMap.get(type); - if (value != undefined) { - this.__nameMap.set(type, value + 1); - return type + "_" + String(value + 1); - } else { - this.__nameMap.set(type, 1); - return type + "_1"; - } - } - - /** - * Returns a connection object corresponding to the ID - * @param {String} id ID of feature to get the connection - * @return {Connection|null} - * @memberof Device - */ - getConnectionForFeatureID(id: string): Connection | null { - for (let i in this.__connections) { - let connection = this.__connections[i]; - //go through each component's features - for (let j in connection.featureIDs) { - let featureid = connection.featureIDs[j]; - if (featureid === id) { - return connection; - } - } - } - - return null; - } - - /** - * Insert a connection between a valve component and the connection component - * @param {Component} valve Valve object - * @param {Connection} connection Connection object - * @memberof Device - * @returns {void} - */ - insertValve(valve: Component, connection: Connection, valvetype: ValveType = ValveType.NORMALLY_OPEN): void { - this.__valveMap.set(valve.id, connection.id); - this.__valveTypeMap.set(valve.id, valvetype); - } - /** - * Returns connections of the device - * @returns {Connections} Connections object - * @memberof Device - */ - get connections(): Array { - return this.__connections; - } - - /** - * Returns a list of valves mapped onto the connection - * @param {Connection} connection Connection object - * @return {Array} - * @memberof Device - */ - getValvesForConnection(connection: Connection): Array { - let connectionid: string = connection.id; - let ret: Array = []; - for (let [key, value] of this.__valveMap) { - // let = pair; - if (connectionid === value) { - let valve = this.getComponentByID(key); - if (valve !== null) { - ret.push(valve); - } - } - } - - return ret; - } - - /** - * Returns whether or not the valve generates a break - * @param {Component} valve Valve device - * @return {any} - * @memberof Device - */ - getValveType(valve: Component): ValveType { - - let valveid = valve.id; - let ret = this.__valveTypeMap.get(valveid); - if (ret === undefined) { - throw new Error("Valve not found"); - } - return ret; - } - - /** - * Returns component object that is identified by the given key - * @param {String} key Key to the component - * @return {Component} - * @memberof Device - */ - getComponentByID(key: string): Component | null { - for (let i in this.__components) { - let component = this.__components[i]; - if (component.id === key) { - return component; - } - } - return null; - //throw new Error("Component with ID " + key + " does not exist"); - } - - /** - * Returns connection object which is identified by a given key - * @param {String} key Key to identify the connection - * @return {Connection} - * @memberof Device - */ - getConnectionByID(key: string): Connection | null { - for (let i in this.__connections) { - let connection = this.__connections[i]; - if (connection.id === key) { - return connection; - } - } - return null; - //throw new Error("Connection with ID " + key + " does not exist"); - } - - /** - * Returns the component given by the user friendly name parameter. Returns null if nothing is found - * @param {String} name - * @return {Component|null} - * @memberof Device - */ - getComponentByName(name: string): Component { - let components = this.__components; - for (const component of components) { - if (name == component.name) { - return component; - } - } - throw new Error("Component with name " + name + "does not exist"); - } - - /** - * Returns a list of connections that have not been routed yet - * @return {Array} - * @memberof Device - */ - getUnroutedConnections(): Array { - let ret: Array = []; - let connections = this.__connections; - for (const connection of connections) { - if (!connection.routed) { - ret.push(connection); - } - } - return ret; - } - /** - * Gets the position of the component port based depending which port you selected - * @param {ComponentPort} componentport Component port object - * @memberof Device - * @returns {Array} Returns array with the absolute positions of the component port - */ - getPositionOfComponentPort(componentport: ComponentPort): Point | undefined { - let components: Array = this.__components; - for (const component of components) { - for (const key of component.ports.keys()) { - let port: undefined | ComponentPort = component.ports.get(key); - if (port != undefined) { - if (componentport.id == port.id) { - //Found the component so return the position - return ComponentPort.calculateAbsolutePosition(componentport, component); - } - } - } - } - } - - /** - * This is the method that is called when one needs to make the feature object. The static function encapsulates - * all the functionality that needs to be implemented. - * @param {string} typeString - * @param {string} setString - * @param {} paramvalues - * @param {string} name - * @param {string} id - * @param {} fabtype - * @param {DXFObject} dxfdata - * @return {EdgeFeature|Feature} - * @memberof Device - */ - static makeFeature( - typeString: string, - paramvalues: any, - name: string = "New Feature", - id: string | undefined = undefined, - fabtype?: string, - dxfdata?: Array | null - ): Feature { - let params: Params = new Params(new Map(), new Map(), new Map()); - - if (typeString === "EDGE") { - //TODO: Put in params initialization - return new EdgeFeature(fabtype, params, id); - } - let featureType = ComponentAPI.getDefinition(typeString); - if (paramvalues && featureType) { - Feature.checkDefaults(paramvalues, featureType.heritable, ComponentAPI.getDefaultsForType(typeString)); - params = new Params(paramvalues, MapUtils.toMap(featureType.unique), MapUtils.toMap(featureType.heritable)); - } else { - let unique: Map = new Map(); - params = new Params(paramvalues, unique.set("position", "Point"), new Map()); - } - - let feature = new Feature(typeString, params, name, id); - if (dxfdata) { - for (let i = 0; i < dxfdata.length; i++) { - feature.addDXFObject(DXFObject.fromJSON(dxfdata[i])); - } - } - - return feature; - } - - get textLayers(): Array { - return this.__textLayers; - } -} diff --git a/src/app/core/dxfObject.ts b/src/app/core/dxfObject.ts deleted file mode 100644 index 0fba548e..00000000 --- a/src/app/core/dxfObject.ts +++ /dev/null @@ -1,76 +0,0 @@ -/** - * DXFObject class - */ -export default class DXFObject { - protected _rootObject: any; - protected _type: string; - - /** - * Default Constructor - * @param {*} jsondata - */ - constructor(jsondata: any) { - this._rootObject = jsondata; - - this._type = jsondata.type; - } - - /** - * Sets type of the object - * @param {String} type - * @memberof DXFObject - * @returns {void} - */ - setType(type: string): void { - this._type = type; - this._rootObject.type = type; - } - - /** - * Gets the type of the object - * @returns {String} Returns type of the object - * @memberof DXFObject - */ - getType(): string { - return this._type; - } - - /** - * Gets the data of the object - * @returns {} Returns the data of the object - * @memberof DXFObject - */ - getData(): any { - return this._rootObject; - } - - /** - * Adds data by passing the key (Name of the data) and it's value - * @param {String} key - * @param {*} value - * @memberof DXFObject - * @returns {void} - */ - addData(key: string, value: any): void { - this._rootObject[key] = value; - } - - /** - * ? - * @returns {Object} - * @memberof DXFObject - */ - toJSON(): JSON { - return this._rootObject; - } - - /** - * - * @param {JSON} json - * @returns {DXFObject} Returns new DXFObject object - * @memberof DXFObject - */ - static fromJSON(json: JSON): DXFObject { - return new DXFObject(json); - } -} diff --git a/src/app/core/edgeFeature.ts b/src/app/core/edgeFeature.ts deleted file mode 100644 index 45f4ef07..00000000 --- a/src/app/core/edgeFeature.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { ComponentAPI } from "@/componentAPI"; -import { DFMType } from "@/app/manufacturing/manufacturingInfo"; -import DXFObject from "./dxfObject"; - -import Feature from "./feature"; -import Params from "./params"; - -/** - * Edge Feature class - */ -export default class EdgeFeature extends Feature { - protected _edgeObjects: any; - - /** - * Default constructor for the edge feature - * @param {Object} edgeObjects - * @param {Params} params - * @param {String} id - */ - constructor(edgeObjects: any, params: Params, id = ComponentAPI.generateID()) { - super("EDGE", params, id, id, DFMType.EDGE); - if (edgeObjects) { - this._edgeObjects = edgeObjects; - } else { - this._edgeObjects = []; - } - } - - /** - * Generate a rectangular edge for the device - * @param {Number} xspan X coordinate - * @param {Number} yspan Y coordinate - * @memberof EdgeFeature - * @returns {void} - */ - generateRectEdge(xspan: number, yspan: number): void { - // TODO: Fix this by trying to incorporate a system where the unit is given - xspan /= 1000; - yspan /= 1000; - const object = new DXFObject({ - type: "POLYLINE", - vertices: [ - { - x: 0, - y: 0, - z: 0 - }, - { - x: xspan, - y: 0, - z: 0 - }, - { - x: xspan, - y: yspan, - z: 0 - }, - { - x: 0, - y: yspan, - z: 0 - }, - { - x: 0, - y: 0, - z: 0 - } - ] - }); - - this.addDXFObject(object); - } -} diff --git a/src/app/core/feature.ts b/src/app/core/feature.ts deleted file mode 100644 index 1dcdf065..00000000 --- a/src/app/core/feature.ts +++ /dev/null @@ -1,445 +0,0 @@ -import CustomComponent from "./customComponent"; -import Params from "./params"; -import Device from "./device"; -import Layer from "./layer"; -import DXFObject from "./dxfObject"; -import { ComponentAPI } from "@/componentAPI"; -import MapUtils from "../utils/mapUtils"; -import { FeatureInterchangeV1_2, LogicalLayerType } from "./init"; -import Parameter from "./parameter"; -import EventBus from "@/events/events"; -import RenderLayer from "../view/renderLayer"; -import { DFMType, ManufacturingInfo } from "../manufacturing/manufacturingInfo"; -import FeatureUtils from "@/app/utils/featureUtils"; - -/** - * Feature class - */ -export default class Feature { - protected _type: string; - protected _params: Params; - protected _name: string; - protected _id: string; - protected _fabtype: DFMType; - protected _dxfObjects: Array; - protected _referenceID: string | null; - public layer: Layer | null; - protected _manufacturingInfo: ManufacturingInfo; - - /** - * Feature Object - * @param {String} type - * @param {} set - * @param {Params} params - * @param {String} name - * @param {String} id - * @param {} fabtype - */ - constructor(type: string, params: Params, name: string, id: string = ComponentAPI.generateID(), fabtype: DFMType = DFMType.XY) { - this._type = type; - this._params = params; - this._name = name; - this._id = id; - this._type = type; - this._fabtype = fabtype; - this._dxfObjects = []; - this._referenceID = null; - this.layer = null; - const tempRenderName: string = this.deriveRenderName(); - let modifierName: string; - if (this.type == "Port") modifierName = "PORT"; - else modifierName = "COMPONENT"; - console.log("rendName: ", tempRenderName); - console.log("z-offset-key: ", ComponentAPI.library[this.type].object.zOffsetKey(tempRenderName)); - this._manufacturingInfo = { - fabtype: fabtype, - layertype: null, - rendername: tempRenderName, - z_offset_key: ComponentAPI.library[this.type].object.zOffsetKey(tempRenderName), - depth: this.getValue(ComponentAPI.library[this.type].object.zOffsetKey(tempRenderName)), - substrate_offset: ComponentAPI.library[this.type].object.substrateOffset(tempRenderName), - substrate: null, - modifier: modifierName - }; - } - - get id(): string { - return this._id; - } - - get type(): string { - return this._type; - } - - /** - * Returns the reference object id - * @return {String} - * @memberof Feature - */ - get referenceID(): string | null { - return this._referenceID; - } - - /** - * Sets the reference object id - * @param {} value - * @memberof Feature - * @returns {void} - * @private - */ - set referenceID(value: string | null) { - this._referenceID = value; - } - - /** - * Sets dxf object - * @param {} dxfdata - * @memberof Feature - * @returns {void} - */ - set dxfObjects(dxfdata: Array) { - this._dxfObjects = dxfdata; - } - - /** - * Returns a string that describes the fabrication type - * @return {DFMType|*} - * @memberof Feature - */ - get fabType(): DFMType { - return this._fabtype; - } - - /** - * Returns the manufacturing information - * @return {ManufacturingInfo} - * @memberof Feature - */ - get manufacturingInfo(): ManufacturingInfo { - this.setManufacturingInfoLayer(); - return this._manufacturingInfo; - } - - /** - * Ensures that layer and substrate values in manufacturingInfo have been set - * @return {void} - * @memberof Feature - */ - setManufacturingInfoLayer(): void { - this._manufacturingInfo.depth = this.getValue(ComponentAPI.library[this.type].object.zOffsetKey(this.deriveRenderName())); - if (this.layer !== null) { - this._manufacturingInfo.layertype = this.layer.type; - this._manufacturingInfo.substrate = FeatureUtils.setSubstrate(this, this._manufacturingInfo.substrate_offset); - } else { - throw new Error("Layer not set in feature " + this.ID + " so manufacturingInfo cannot be set"); - } - } - - /** - * Updates the parameter stored for the given key - * @param {String} key Key to identify the parameter - * @param {} value New value to be assigned to the parameter - * @memberof Feature - * @returns {void} - */ - updateParameter(key: string, value: any): void { - this._params.updateParameter(key, value); - EventBus.get().emit(EventBus.UPDATE_RENDERS, this); - } - - /** - * Generates the serial version of this object - * @returns {Feature} Returns Feature object in JSON format - * @memberof Feature - */ - toJSON() { - const output = { - id: this._id, - name: this._name, - type: this._type, - params: this._params.toJSON() - }; - - return output; - } - - /** - * Generates the serial version of this object but conforms to the interchange format - * @returns {} - * @memberof Feature - */ - toInterchangeV1(): FeatureInterchangeV1_2 { - // TODO: We need to figure out what to do and what the final feature format will be - const output = { - id: this._id, - name: this._name, - macro: this._type, - params: this._params.toJSON(), - type: this._fabtype, - referenceID: this._referenceID, - dxfData: this._dxfObjects.map(function(dxfObject) { - return dxfObject.toJSON(); - }), - layerID: this.layer?.id ?? "", - }; - return output; - } - - /** - * Gets dxfObject - * @returns {DXFObject} - * @memberof Feature - */ - get dxfObjects() { - return this._dxfObjects; - } - - /** - * Gets the ID of the object - * @returns {String} Returns the ID - * @memberof Feature - */ - get ID() { - return this._id; - } - - /** - * Set the name of the object - * @param {String} name - * @memberof Feature - * @returns {void} - */ - setName(name: string): void { - this._name = name; - } - - /** - * Gets the name of the feature object - * @returns {String} Returns the name of the feature object - * @memberof Feature - * - */ - getName(): string { - return this._name; - } - - /** - * Gets type of the feature object - * @returns {String} Returns the type of the object - * @memberof Feature - */ - getType(): string { - return this._type; - } - - /** - * Gets the value of certain feature by passing a key identifier - * @param {String} key Key is use to identify the desire feature - * @returns {} Returns the value of the parameters - * @memberof Feature - */ - getValue(key: string) { - try { - return this._params.getValue(key); - } catch (err) { - if (this.hasDefaultParam(key)) return this.getDefaults()[key]; - else throw new Error("Unable to get value for key: " + key); - } - } - - /** - * Checks if the feature object corresponding to the key passed has default parameters. - * @param {String} key - * @returns {boolean} Returns true if it has default parameters - * @memberof Feature - */ - hasDefaultParam(key: string): boolean { - if (this.getDefaults().hasOwnProperty(key)) return true; - else return false; - } - - /** - * Checks if the feature object has unique parameters. To select object, a key identifier is requiered - * @param {String} key - * @returns {boolean} - * @memberof Feature - */ - hasUniqueParam(key: string): boolean { - return this._params.isUnique(key); - } - - /** - * Checks if the feature object has heritable parameters. To select object, a key identifier is requiered - * @param {String} key - * @returns {boolean} - * @memberof Feature - */ - hasHeritableParam(key: string): boolean { - return this._params.isHeritable(key); - } - - /** - * Gets the heritable parameters of the feature object - * @returns {Array} Returns the heritable parameters of the feature object - * @memberof Feature - */ - getHeritableParams(): { [key: string]: string } { - return ComponentAPI.getHeritableForType(this.getType()); - } - - /** - * Gets the unique parameters of the feature object - * @returns {Array} Returns the unique parameters of the feature object - * @memberof Feature - */ - getUniqueParams(): { [key: string]: string } { - return ComponentAPI.getUniqueForType(this.getType()); - } - - /** - * Gets the default parameters of the feature object - * @returns {Array} Returns the default paramets of the feature object - * @memberof Feature - */ - getDefaults(): { [key: string]: number } { - return ComponentAPI.getDefaultsForType(this.getType()); - } - - /** - * Gets the parameters of the feature object - * @returns {Array} Returns the parameters of the feature object - * @memberof Feature - */ - getParams(): { [index: string]: Parameter } { - return this._params.parameters; - } - - /** - * Sets the passed parameter as a parameter of the feature object - * @param {Params} params New parameter to the object - * @memberof Feature - * @returns {void} - */ - setParams(params: { [index: string]: Parameter }): void { - this._params.loadParameters(params); - } - - /** - * Replicates the position - * @param {Number} xpos X coordinate to replicate - * @param {Number} ypos Y coordinate to replicate - * @returns {Feature} - * @memberof Feature - */ - replicate(xpos: number, ypos: number): Feature { - const paramscopy = this._params; - const replicaparams: { [key: string]: any } = { - position: [xpos, ypos] - }; - for (const key in this._params.parameters) { - replicaparams[key] = this.getValue(key); - } - - const ret = Device.makeFeature( - this._type, - replicaparams, - this._name, - ComponentAPI.generateID(), - "XY", - this._dxfObjects.map(function(dxfObject) { - return dxfObject.toJSON(); - }) - ); - - return ret; - } - - /** - * Determines the string which should be used for the renderName - * @returns Returns the render name - * @memberof Feature - */ - - deriveRenderName(): string { - if (!ComponentAPI.library[this.type]) { - console.error("Type unrecognized, defaulting to template."); - this._type = "Template"; - } - return ComponentAPI.library[this.type].key; - } - - /** - * Checks whether the values do not have an own property and assigns them a default value. - * @param {*} values - * @param {*} heritable - * @param {*} defaults - * @returns Returns the values - * @memberof Feature - */ - static checkDefaults(values: { [key: string]: number }, heritable: { [key: string]: string }, defaults: { [key: string]: number }) { - for (const key in heritable) { - if (!Object.prototype.hasOwnProperty.call(values, key)) values[key] = defaults[key]; - } - return values; - } - - /** - * Loads from JSON format the features for a device - * @param {JSON} json - * @returns {Feature} Returns a Device object with the features in the JSON - * @memberof Feature - */ - static fromJSON(json: any) { - return Device.makeFeature(json.type, json.params, json.name, json.id, "XY", []); - } - - /** - * Loads from an InetchangeV1 format the features for a device object - * @param {*} json - * @returns {Feature} - * @memberof Feature - */ - static fromInterchangeV1(json: any) { - let ret; - // TODO: This will have to change soon when the thing is updated - ret = Device.makeFeature(json.macro, json.params, json.name, json.id, json.type, json.dxfData); - if (Object.prototype.hasOwnProperty.call(json, "referenceID")) { - ret.referenceID = json.referenceID; - // Registry.currentDevice.updateObjectReference(json.id, json.referenceID); - } - return ret; - } - - /** - * Creates a custom feature for the component based on the parameters values - * @returns {Feature} Returns a new feature object - * @memberof Feature - */ - static makeCustomComponentFeature(customcomponent: CustomComponent, setstring: string, paramvalues: { [key: string]: any }, name = "New Feature", id = undefined) { - const definitions = CustomComponent.defaultParameterDefinitions(); - Feature.checkDefaults(paramvalues, definitions.heritable, ComponentAPI.getDefaultsForType(customcomponent.type)); - const params = new Params(paramvalues, MapUtils.toMap(definitions.unique), MapUtils.toMap(definitions.heritable)); - const ret = new Feature(customcomponent.type, params, name, id, DFMType.XY); - ret.dxfObjects = customcomponent.dxfData; - return ret; - } - - /** - * Returns the dxf objects - * @return {DXFObject} - * @memberof Feature - */ - getDXFObjects(): Array { - return this._dxfObjects; - } - - /** - * Add a DXF object - * @param {DXFObject} dxfobject - * @memberof Feature - * @returns {void} - */ - addDXFObject(dxfobject: DXFObject): void { - this._dxfObjects.push(dxfobject); - } -} diff --git a/src/app/core/geometryElement.ts b/src/app/core/geometryElement.ts deleted file mode 100644 index 01f9847d..00000000 --- a/src/app/core/geometryElement.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { ComponentAPI } from "@/componentAPI"; -import { GeometricOperationType, GeometryElementInterchangeV1_2 } from "./init"; -import Layer from "./layer"; -import Params from "./params"; - -export default class GeometryElement { - - private _id: string; - private _macro: string; - private _geometricOperation: GeometricOperationType; - private _layer: Layer; - - private _params: Params; - - constructor(id: string = ComponentAPI.generateID(), macro:string, geometricOperation: GeometricOperationType, layer: Layer, params: { [k: string]: any } = {}) { - this._id = id; - this._macro = macro; - this._geometricOperation = geometricOperation; - this._layer = layer; - - // Initilize the params - this._params = new Params(params, new Map(), new Map()); - } - - get id(): string { - return this._id; - } - - get type(): string { - return this._macro; - } - - get geometricOperation(): GeometricOperationType { - return this._geometricOperation; - } - - get layer(): Layer { - return this._layer; - } - - get params(): Params { - return this._params; - } - - toInterchageV1_2(): GeometryElementInterchangeV1_2 { - return { - id: this._id, - macro: this._macro, - params: this._params.toJSON(), - geometricOperation: this._geometricOperation, - mgflayerID: this._layer.id - }; - } -} \ No newline at end of file diff --git a/src/app/core/init.ts b/src/app/core/init.ts deleted file mode 100644 index fd2e2731..00000000 --- a/src/app/core/init.ts +++ /dev/null @@ -1,144 +0,0 @@ -export type Point = [number, number]; - -export type Segment = [Point, Point]; - -export type ParamsInterchangeType = {[key: string]: any}; - -export type ToolPaperObject = paper.CompoundPath | paper.Path | paper.PointText | paper.PathItem; - -export type InterchangeV1_2 = { - name: string; - params: ParamsInterchangeType; - layers: Array; - groups: Array; - components: Array; - connections: Array; - valves: Array; - version: string; - renderLayers: Array; - features: Array; -}; - -export enum LogicalLayerType { - FLOW = "FLOW", - CONTROL = "CONTROL", - INTEGRATION = "INTEGRATION" -} - -export enum ValveType { - NORMALLY_OPEN = "NORMALLY_OPEN", - NORMALLY_CLOSED = "NORMALLY_CLOSED", -} - -export enum GeometricOperationType{ - UNION = "UNION", - INTERSECTION = "INTERSECTION", - DIFFERENCE = "SUBTRACTION", - XOR = "XOR", -} - -export type DeviceInterchangeV1 = { - name: string; - params: ParamsInterchangeType; - layers: Array; - groups: Array; - components: Array; - connections: Array; - valves: Array; - version: string; -}; - -export type DeviceInterchangeV1_1 = { - name: string; - params: ParamsInterchangeType; - layers: Array; - groups: Array; - components: Array; - connections: Array; - version: string; -}; - -export type ComponentInterchangeV1 = { - id: string; - name: string; - entity: string; - params: ParamsInterchangeType; - "x-span": number; - "y-span": number; - ports: Array; - layers: Array; -}; - -export type ConnectionInterchangeV1_2 = { - id: string; - name: string; - entity: string; - source: ConnectionTargetInterchangeV1; - sinks: Array; - paths: Array; - params: ParamsInterchangeType; - layer: string; -}; - -export type ValveInterchangeV1_2 = { - componentid: string; - connectionid: string; - type: ValveType; - params: ParamsInterchangeType; -} - -export type LayerInterchangeV1 = { - id: string; - name: string; - params: ParamsInterchangeType; - group: string; - type: string; - features: Array; -}; - -export type RenderLayerInterchangeV1_2 = { - id: string; - features: Array; - modellayer: string | null; - color: string | undefined; - name: string; - type: string; -}; - -export type FeatureInterchangeV1_2 = { - id: string; - name: string; - macro: string; - layerID: string | null; - referenceID: string | null; // Delete this in the future - params: ParamsInterchangeType; - dxfData: any; // 3DuF specific data for raw import/export of DXF objects - type: string; -}; - -export type GeometryElementInterchangeV1_2 = { - id: string; - macro: string; - params: ParamsInterchangeType; - geometricOperation: string; - mgflayerID: string; -} - -export type ComponentPortInterchangeV1 = { - x: number; - y: number; - label: string; - layer: string; -}; - -export type ConnectionTargetInterchangeV1 = { - component: string; - port: string; -}; - -export type ConnectionPathInterchangeV1_2 = { - wayPoints: Array; - source: ConnectionTargetInterchangeV1 | null; - sink: ConnectionTargetInterchangeV1 | null; - features: Array; -}; diff --git a/src/app/core/layer.ts b/src/app/core/layer.ts deleted file mode 100644 index 5dc49c58..00000000 --- a/src/app/core/layer.ts +++ /dev/null @@ -1,360 +0,0 @@ -import uuid from "node-uuid"; -import EdgeFeature from "./edgeFeature"; -import Feature from "./feature"; -import Params from "./params"; -import Device from "./device"; -import { FeatureInterchangeV1_2 } from "./init"; -import { LayerInterchangeV1, LogicalLayerType } from "./init"; -import { ComponentAPI } from "@/componentAPI"; - -/** - * Layer class - */ -export default class Layer { - params: Params; - name: string; - features: { [index: string]: Feature }; - featureCount: number; - device?: Device; - private __id: string; - private __type: LogicalLayerType = LogicalLayerType.FLOW; - private __group: string; - - /** - * Default Constructor for the layer - * @param {*} values Value of the layer - * @param {String} name Name of the layer - */ - constructor(values: { [index: string]: any }, name: string = "New Layer", type: LogicalLayerType = LogicalLayerType.FLOW, group: string = "0", device?: Device) { - this.params = new Params(values, Layer.getUniqueParameters(), Layer.getHeritableParameters()); - this.name = name; - this.features = {}; - this.featureCount = 0; - this.device = device; - this.__id = ComponentAPI.generateID(); - this.__type = type; - this.__group = group; - } - - get type(): LogicalLayerType { - return this.__type; - } - - get id(): string { - return this.__id; - } - - set id(ID: string) { - this.__id = ID; - } - - get group(): string { - return this.__group; - } - - /** - * Adds a feature to the layer - * @param {Feature} feature Feature to pass to add to the layer - * @memberof Layer - * @returns {void} - */ - addFeature(feature: Feature): void { - this.__ensureIsAFeature(feature); - this.features[feature.ID] = feature; - this.featureCount += 1; - //TODO - Verify that this is not a problem anymore - feature.layer = this; - feature.setManufacturingInfoLayer(); - } - - /** - * Returns index of layer - * @returns {Number} - * @memberof Layer - */ - getIndex(): number { - if (this.device) { - return this.device.layers.indexOf(this); - } else { - throw new Error("No device referenced on this layer"); - } - } - /* - estimateLayerHeight(){ - let dev = this.device; - let flip = this.params.getValue("flip"); - let offset = this.params.getValue("z_offset"); - if (dev){ - let thisIndex = this.getIndex(); - let targetIndex; - if (flip) targetIndex = thisIndex - 1; - else targetIndex = thisIndex + 1; - if (thisIndex >= 0 || thisIndex <= (dev.layers.length -1)){ - let targetLayer = dev.layers[targetIndex]; - return Math.abs(offset - targetLayer.params.getValue("z_offset")); - } else { - if (thisIndex -1 >= 0){ - let targetLayer = dev.layers[thisIndex -1]; - return targetLayer.estimateLayerHeight(); - } - } - } - return 0; - } -*/ - - /** - * Checks whether the argument pass is a feature - * @param {Feature} feature Feature object - * @memberof Layer - * @returns {void} - */ - __ensureIsAFeature(feature: any): void { - if (!(feature instanceof Feature) && !(feature instanceof EdgeFeature)) { - throw new Error("Provided value" + feature + " is not a Feature! Did you pass an ID by mistake?"); - } - } - - /** - * Checks whether the feature already exist - * @param {Feature} feature Feature object - * @memberof Layer - * @returns {void} - */ - __ensureFeatureExists(feature: Feature): void { - if (!this.containsFeature(feature)) throw new Error("Layer does not contain the specified feature!"); - } - - /** - * Checks if feature exist based on it's ID - * @param {String} featureID ID of the feature to search for - * @memberof Layer - * @returns {void} - */ - __ensureFeatureIDExists(featureID: string): void { - if (!this.containsFeatureID(featureID)) throw new Error("Layer does not contain a feature with the specified ID!"); - } - - /** - * Returns unique parameters - * @returns {Map} - * @memberof Layer - * @returns {void} - */ - static getUniqueParameters(): Map { - let unique: Map = new Map(); - unique.set("z_offset", "Float"); - unique.set("flip", "Boolean"); - return unique; - } - - /** - * Returns heritable parameters - * @returns {Map} - * @memberof Layer - * @returns {void} - */ - static getHeritableParameters(): Map { - return new Map(); - } - - /** - * Returns feature based on it's ID - * @param {String} featureID - * @returns {Feature} - * @memberof Layer - */ - getFeature(featureID: string): Feature { - this.__ensureFeatureIDExists(featureID); - return this.features[featureID]; - } - - /** - * Removes selected feature - * @param {Feature} feature Feature object - * @memberof Layer - * @returns {void} - */ - removeFeature(feature: Feature): void { - this.removeFeatureByID(feature.ID); - console.log("Device: ", this.device); - if (this.device !== null || this.device !== undefined) { - this.device?.removeFeature(feature); - } - } - - // TODO: Stop using delete, it's slow! - /** - * Removes a feature by passing it's ID as a parameter - * @param {string} featureID ID of the feature - * @memberof Layer - * @returns {void} - */ - removeFeatureByID(featureID: string): void { - this.__ensureFeatureIDExists(featureID); - const feature: Feature = this.features[featureID]; - this.featureCount -= 1; - delete this.features[featureID]; - } - - /** - * Checks if object contains a feature - * @param {Feature} feature Feature object - * @returns {Boolean} true if it has the feature - * @memberof Layer - */ - containsFeature(feature: Feature): boolean { - this.__ensureIsAFeature(feature); - return this.features.hasOwnProperty(feature.ID); - } - - /** - * Checks if object contains a feature based on the feature's ID - * @param {String} featureID ID of the feature to search for - * @returns {Boolean} true if it has the feature - * @memberof Layer - */ - containsFeatureID(featureID: string): boolean { - return this.features.hasOwnProperty(featureID); - } - - /** - * Gets all features from the layers - * @returns {Array} Returns all features from the layers - * @memberof Layer - */ - getAllFeaturesFromLayer(): { [index: string]: Feature } { - return this.features; - } - - /** - * Convers features to JSON format - * @returns {JSON} Returns a JSON format with the features in a JSON format - * @memberof Layer - */ - __featuresToJSON(): { [index: string]: any } { - const output: { [index: string]: any } = {}; - for (const i in this.features) { - output[i] = this.features[i].toJSON(); - } - return output; - } - - /** - * Converts features to Interchange format - * @returns {Array} Returns an array with the features in Interchange format - * @memberof Layer - */ - __featuresInterchangeV1(): Array { - const output: Array = []; - for (const i in this.features) { - output.push(this.features[i].toInterchangeV1()); - } - return output; - } - - /** - * Loads features from JSON format - * @param {JSON} json JSON format file - * @memberof Layer - */ - __loadFeaturesFromJSON(json: { [index: string]: any }): void { - for (const i in json) { - this.addFeature(Feature.fromJSON(json[i])); - } - } - - /** - * Loads features from Interchange format - * @param {*} json Interchange format file - * @memberof Layer - */ - __loadFeaturesFromInterchangeV1(json: { [index: string]: any }): void { - for (const i in json) { - this.addFeature(Feature.fromInterchangeV1(json[i])); - } - } - - // TODO: Replace Params and remove static method - /** - * Converts the attributes of the object into a JSON format - * @returns {JSON} Returns a JSON format with the attributes of the object - * @memberof Layer - */ - toJSON(): { [index: string]: any } { - const output: { [index: string]: any } = {}; - output.name = this.name; - output.params = this.params.toJSON(); - output.features = this.__featuresToJSON(); - return output; - } - - /** - * Converts the attributes of the object into Interchange format - * @returns {LayerInterchangeV1} Returns a Interchange format with the attributes of the object - * @memberof Layer - */ - toInterchangeV1(): LayerInterchangeV1 { - let layerType = "FLOW"; - if (this.type === LogicalLayerType.FLOW) { - layerType = "FLOW"; - } else if (this.type === LogicalLayerType.CONTROL) { - layerType = "CONTROL"; - } else if (this.type === LogicalLayerType.INTEGRATION) { - layerType = "INTEGRATION"; - } else { - throw new Error("Unknown layer type: " + this.type); - } - - const output: LayerInterchangeV1 = { - id: this.__id, - name: this.name, - type: layerType, - // TODO - Add group and unique name parameters to the system and do type checking - // against type and not name in the future - group: this.__group, - params: this.params.toJSON(), - features: this.__featuresInterchangeV1() - }; - return output; - } - - /** - * Generate the feature layer json that is neccissary for - * seriailizing the visual of the 3DuF designs - * - * @returns {*} json of the features - * @memberof Layer - */ - toFeatureLayerJSON(): { [index: string]: any } { - const output: { [index: string]: any } = {}; - output.name = this.name; - output.params = this.params.toJSON(); - output.features = this.__featuresInterchangeV1(); - return output; - } - - /** - * Load from an Interchange format a new layer object - * @param {*} json - * @returns {Layer} Returns a new layer object - * @memberof Layer - */ - static fromInterchangeV1(json: LayerInterchangeV1, device: Device): Layer { - let layerType = LogicalLayerType.FLOW; - if (Object.prototype.hasOwnProperty.call(json, "type")) { - if (json.type === "FLOW") { - layerType = LogicalLayerType.FLOW; - } else if (json.type === "CONTROL") { - layerType = LogicalLayerType.CONTROL; - } else if (json.type === "INTEGRATION") { - layerType = LogicalLayerType.INTEGRATION; - } else { - throw new Error("Unknown layer type: " + json.type); - } - } - const newLayer: Layer = new Layer(json.params, json.name, layerType, json.group, device); - newLayer.__loadFeaturesFromInterchangeV1(json.features); - return newLayer; - } -} diff --git a/src/app/core/parameter.ts b/src/app/core/parameter.ts deleted file mode 100644 index b7e5b061..00000000 --- a/src/app/core/parameter.ts +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Parameter class - */ -export default class Parameter { - private __type: string; - private __value: any; - - /** - * Default Constructor of the Parameter object - * @param {String} type - * @param {*} value - */ - constructor(type: string, value: any) { - //Check value if its parsable string - if (typeof value === "string" && type === "Float") { - value = parseInt(value); - } else if (typeof value === "string" && type === "Integer") { - value = parseInt(value); - } - //Parameter.checkValue(type, value); - this.__type = type; - this.__value = value; - } - /** - * @returns {} - * @memberof Parameter - */ - toJSON(): any { - return this.__value; - } - /** - * Gets value of parameter - * @returns {} Returns value of the parameter - * @memberof Parameter - */ - public get value(): any { - return this.__value; - } - /** - * Gets type of parameter - * @returns {String} Returns the type of parameter - * @memberof Parameter - */ - public get type(): string { - return this.__type; - } - - /** - * Updates the value of parameter - * @param {*} value New value of the parameter - * @memberof Parameter - * @returns {void} - */ - updateValue(value: any): void { - //Parameter.checkValue(this.__type, value); - this.__value = value; - } - - resetValue(): void {} -} diff --git a/src/app/core/parameters/booleanValue.ts b/src/app/core/parameters/booleanValue.ts deleted file mode 100644 index 7d55a746..00000000 --- a/src/app/core/parameters/booleanValue.ts +++ /dev/null @@ -1,15 +0,0 @@ -import Parameter from "../parameter"; - -export default class BooleanValue extends Parameter { - static readonly typeString: string = "Boolean"; - static readonly description: string = "BooleanValue must be true or false."; - - constructor(value: boolean) { - super("Boolean", value); - } - - static isValid(value: any): boolean { - if (typeof value === "boolean") return true; - else return false; - } -} diff --git a/src/app/core/parameters/floatValue.ts b/src/app/core/parameters/floatValue.ts deleted file mode 100644 index c12224f9..00000000 --- a/src/app/core/parameters/floatValue.ts +++ /dev/null @@ -1,16 +0,0 @@ -import Parameter from "../parameter"; -import * as NumberUtils from "../../utils/numberUtils"; - -export default class FloatValue extends Parameter { - static readonly typeString: string = "Float"; - static readonly description: string = "FloatValue must be a number >= 0, such as 3.827"; - - constructor(value: number) { - super("Float", value); - } - - static isValid(value: any): boolean { - if (typeof value === "number" && NumberUtils.isFloatOrInt(value) && value >= 0) return true; - else return false; - } -} diff --git a/src/app/core/parameters/integerValue.ts b/src/app/core/parameters/integerValue.ts deleted file mode 100644 index eb6d2d8e..00000000 --- a/src/app/core/parameters/integerValue.ts +++ /dev/null @@ -1,16 +0,0 @@ -import Parameter from "../parameter"; -import * as NumberUtils from "../../utils/numberUtils"; - -export default class IntegerValue extends Parameter { - static readonly typeString: string = "Integer"; - static readonly description: string = "FloatValue must be an integer >= 0."; - - constructor(value: number) { - super("Integer", value); - } - - static isValid(value: any): boolean { - if (typeof value === "number" && NumberUtils.isInteger(value) && value >= 0) return true; - else return false; - } -} diff --git a/src/app/core/parameters/pointArray.ts b/src/app/core/parameters/pointArray.ts deleted file mode 100644 index 7a158523..00000000 --- a/src/app/core/parameters/pointArray.ts +++ /dev/null @@ -1,29 +0,0 @@ -import Parameter from "../parameter"; -import pointValue from "./pointValue"; -import { Segment } from "@/app/core/init"; - -export default class PointArray extends Parameter { - static readonly typeString: string = "PointArray"; - static readonly description: string = "Should be an array of points"; - - constructor(value: Segment) { - super("PointArray", value); - } - - static isValid(value: any): boolean { - if (value instanceof Array) { - if (value.length == 0) { - return true; - } - for (var i in value) { - if (!pointValue.isValid(i)) { - console.log("Does not contain a valid point"); - return false; - } - } - } else { - return false; - } - return true; - } -} diff --git a/src/app/core/parameters/pointValue.ts b/src/app/core/parameters/pointValue.ts deleted file mode 100644 index e086b661..00000000 --- a/src/app/core/parameters/pointValue.ts +++ /dev/null @@ -1,17 +0,0 @@ -import Parameter from "../parameter"; -import * as NumberUtils from "../../utils/numberUtils"; -import { Point } from "@/app/core/init"; - -export default class PointValue extends Parameter { - static readonly typeString: string = "Point"; - static readonly description: string = "PointValue must be an array containing exactly two numbers, such as [3,-5]"; - - constructor(value: Point) { - super("Point", value); - } - - static isValid(value: any): boolean { - if (value instanceof Array && value.length == 2 && NumberUtils.isFloatOrInt(value[0]) && NumberUtils.isFloatOrInt(value[1])) return true; - else return false; - } -} diff --git a/src/app/core/parameters/segmentArray.ts b/src/app/core/parameters/segmentArray.ts deleted file mode 100644 index 706a4718..00000000 --- a/src/app/core/parameters/segmentArray.ts +++ /dev/null @@ -1,29 +0,0 @@ -import Parameter from "../parameter"; -import pointArray from "./pointArray"; -import { Segment } from "@/app/core/init"; - -export default class SegmentArray extends Parameter { - static readonly typeString: string = "SegmentArray"; - static readonly description: string = "Should be an array of PointArrays"; - - constructor(value: Array) { - super("SegmentArray", value); - } - - static isValid(value: any): boolean { - if (value instanceof Array) { - if (value.length == 0) { - return true; - } - for (var i in value) { - if (!pointArray.isValid(i)) { - console.log("Does not contain a valid point"); - return false; - } - } - } else { - return false; - } - return true; - } -} diff --git a/src/app/core/parameters/stringValue.ts b/src/app/core/parameters/stringValue.ts deleted file mode 100644 index a99ab97c..00000000 --- a/src/app/core/parameters/stringValue.ts +++ /dev/null @@ -1,15 +0,0 @@ -import Parameter from "../parameter"; - -export default class StringValue extends Parameter { - static readonly typeString: string = "String"; - static readonly description: string = "StringValue must be a String, such as 'foobar'"; - - constructor(value: string) { - super("String", value); - } - - static isValid(value: any): boolean { - if (typeof value === "string" || value instanceof String) return true; - else return false; - } -} diff --git a/src/app/core/params.ts b/src/app/core/params.ts deleted file mode 100644 index 9761c6a7..00000000 --- a/src/app/core/params.ts +++ /dev/null @@ -1,172 +0,0 @@ -/// -import Parameter from "./parameter"; -/** - * Params class - */ -export default class Params { - private __unique: Map; - private __heritable: Map; - private __parameters: { [index: string]: Parameter }; - - /** - * Default constructor create a Params object. - * @param {} values Values of the params - * @param {Boolean} unique Boolean if it's unique - * @param {} heritable Boolean if it's heritable - */ - constructor(values: { [index: string]: any }, unique: Map, heritable: Map) { - this.__unique = unique; - this.__heritable = heritable; - this.__parameters = {}; - for (let key in values) { - this.__parameters[key] = new Parameter(typeof values[key], values[key]); - } - } - - /** - * Returns the parameters object (TODO - Remove this in the future) - * - * @readonly - * @memberof Params - */ - get parameters(): { [index: string]: Parameter } { - return this.__parameters; - } - - /** - * Updates parameter value. - * @param {String} key Identifier of the parameter - * @param {*} value New value of the parameter - * @memberof Params - * @returns {void} - */ - updateParameter(key: string, value: any): void { - if (this.__parameters.hasOwnProperty(key)) { - this.__parameters[key].updateValue(value); - } else { - throw new Error(key + "parameter does not exist in Params object"); - } - } - /** - * Checks if the object has certain parameter. - * @param {String} key The key is use to identify the parameter - * @memberof Params - * @returns {void} - */ - __ensureHasKey(key: string): void { - if (!this.__parameters.hasOwnProperty(key)) throw new Error(key + " parameter not found in Params object."); - } - /** - * Gets the value of the selected parameter. - * @param {String} key The key is needed to identify the parameter - * @returns Returns parameter value - * @memberof Params - */ - getValue(key: string): any { - this.__ensureHasKey(key); - return this.__parameters[key].value; - } - - /** - * Checks if param object has unique key. - * @param {String} key Key to identify the param - * @returns {boolean} - * @memberof Params - */ - isUnique(key: string): boolean { - return this.__unique.has(key); - } - /** - * Checks if param object has heritable attribute. - * @param {String} key Key to identify the param - * @returns {boolean} - * @memberof Params - */ - isHeritable(key: string): boolean { - return this.__heritable.has(key); - } - - /** - * Converts to JSON format. - * @returns {JSON} Returns JSON format. - * @memberof Params - */ - toJSON(): { [index: string]: any } { - let json: { [index: string]: any } = {}; - for (let key in this.__parameters) { - if (this.__parameters[key] != undefined) { - json[key] = this.__parameters[key].value; - } - } - return json; - } - /** - * Creates new params object from a JSON format. - * @param {JSON} json - * @param {*} unique - * @param {*} heritable - * @returns {Params} Returns a new params object. - * @memberof Params - */ - static fromJSON(json: Map, unique: Map, heritable: Map): Params { - return new Params(json, unique, heritable); - } - /** - * Checks if it has parameters. - * @param {String} key The key is use to identify the desire parameter. - * @returns {boolean} - * @memberof Params - */ - hasParam(key: string): boolean { - return this.__parameters.hasOwnProperty(key); - } - - /** - * Returns a ES6 Map() type object with keys and values. - * @return {Map} - * @memberof Params - */ - toMap(): Map { - let ret = new Map(); - for (let key in this.__parameters) { - if (this.__parameters[key] != undefined) { - ret.set(key, this.__parameters[key].value); - } - } - return ret; - } - - /** - * Sets the parameters of the params - * - * @param {{ [index: string]: Parameter }} parameters - * @memberof Params - */ - loadParameters(parameters: { [index: string]: Parameter }): void { - for (let key in parameters) { - this.__parameters[key] = parameters[key]; - } - } - - /** - * Returns the list of unique keys of the params. - * - * @readonly - * @type {Array} - * @memberof Params - */ - get unique(): Array { - return Array.from(this.__unique.keys()); - } - - /** - * Returns the list of heritable keys of the params. - * - * @readonly - * @type {Array} - * @memberof Params - */ - get heritable(): Array { - return Array.from(this.__heritable.keys()); - } -} diff --git a/src/app/core/registry.ts b/src/app/core/registry.ts deleted file mode 100644 index 7db17568..00000000 --- a/src/app/core/registry.ts +++ /dev/null @@ -1,31 +0,0 @@ -import uuid from "node-uuid"; -import RenderLayer from "../view/renderLayer"; -import ViewManager from "../view/viewManager"; -import AdaptiveGrid from "../view/grid/adaptiveGrid"; -import Device from "./device"; -import Layer from "./layer"; - -class Registry { - /* - Place where we store the data necessary for the text label - TODO: Change this from this awful hacky implementation - */ - constructor() { - // registerSets({ Basic: Basic }); - } - - //TODO: Convert this into multiple text layers for use with multiple layers - id_counter = 0; - threeRenderer = null; - - public currentDevice: Device | null = null; - canvasManager = null; - currentTextLayer: Layer | null = null; - currentGrid: AdaptiveGrid | null = null; - view = null; - viewManager: ViewManager | null = null; -} - -const instance = new Registry(); - -export default instance; diff --git a/src/app/examples/dafdtemplate.json b/src/app/examples/dafdtemplate.json deleted file mode 100644 index 3d9ba8d8..00000000 --- a/src/app/examples/dafdtemplate.json +++ /dev/null @@ -1,235 +0,0 @@ -{ - "name": "DAFD Template", - "params": { "width": 135000, "length": 85000 }, - "components": [ - { - "id": "e958b4d0-6155-11e9-89ad-d58be75aeb6f", - "name": "Port_in", - "entity": "PORT", - "params": { "position": [30000, 40000], "portRadius": 1998, "height": 1100 }, - "xspan": 3996, - "yspan": 3996, - "ports": [] - }, - { - "id": "eadf7be0-6155-11e9-89ad-d58be75aeb6f", - "name": "Port_out", - "entity": "PORT", - "params": { "position": [110000, 40000], "portRadius": 1998, "height": 1100 }, - "xspan": 3996, - "yspan": 3996, - "ports": [] - }, - { - "id": "ec125690-6155-11e9-89ad-d58be75aeb6f", - "name": "Port_oil1", - "entity": "PORT", - "params": { "position": [60000, 10000], "portRadius": 1998, "height": 1100 }, - "xspan": 3996, - "yspan": 3996, - "ports": [] - }, - { - "id": "f0839360-6155-11e9-89ad-d58be75aeb6f", - "name": "Port_oil2", - "entity": "PORT", - "params": { "position": [60000, 70000], "portRadius": 1998, "height": 1100 }, - "xspan": 3996, - "yspan": 3996, - "ports": [] - }, - { - "id": "b6d5c690-d628-11e9-9185-859b5727feb8", - "name": "DropletGen_1", - "entity": "NOZZLE DROPLET GENERATOR", - "params": { - "position": [60000, 40000], - "orificeSize": 200, - "orificeLength": 400, - "oilInputWidth": 800, - "waterInputWidth": 600, - "outputWidth": 600, - "outputLength": 600, - "height": 250 - }, - "xspan": 1800, - "yspan": 600, - "ports": [ - { "x": 400, "y": -300, "layer": "FLOW", "label": "1" }, - { "x": 1800, "y": 0, "layer": "FLOW", "label": "2" }, - { "x": 400, "y": 300, "layer": "FLOW", "label": "3" }, - { "x": 0, "y": 0, "layer": "FLOW", "label": "4" } - ] - } - ], - "connections": [], - "features": [ - { - "name": "flow", - "color": "indigo", - "params": { "z_offset": 0, "flip": false }, - "features": { - "e957f180-6155-11e9-89ad-d58be75aeb6f": { - "id": "e957f180-6155-11e9-89ad-d58be75aeb6f", - "name": "New Feature", - "macro": "Port", - "set": "Basic", - "referenceID": "e958b4d0-6155-11e9-89ad-d58be75aeb6f", - "params": { "position": [30000, 40000], "portRadius": 1998, "height": 1100 }, - "dxfData": [], - "type": "XY" - }, - "eadf06b0-6155-11e9-89ad-d58be75aeb6f": { - "id": "eadf06b0-6155-11e9-89ad-d58be75aeb6f", - "name": "New Feature", - "macro": "Port", - "set": "Basic", - "referenceID": "eadf7be0-6155-11e9-89ad-d58be75aeb6f", - "params": { "position": [110000, 40000], "portRadius": 1998, "height": 1100 }, - "dxfData": [], - "type": "XY" - }, - "ec119340-6155-11e9-89ad-d58be75aeb6f": { - "id": "ec119340-6155-11e9-89ad-d58be75aeb6f", - "name": "New Feature", - "macro": "Port", - "set": "Basic", - "referenceID": "ec125690-6155-11e9-89ad-d58be75aeb6f", - "params": { "position": [60000, 10000], "portRadius": 1998, "height": 1100 }, - "dxfData": [], - "type": "XY" - }, - "f082f720-6155-11e9-89ad-d58be75aeb6f": { - "id": "f082f720-6155-11e9-89ad-d58be75aeb6f", - "name": "New Feature", - "macro": "Port", - "set": "Basic", - "referenceID": "f0839360-6155-11e9-89ad-d58be75aeb6f", - "params": { "position": [60000, 70000], "portRadius": 1998, "height": 1100 }, - "dxfData": [], - "type": "XY" - }, - "2ea7a050-6156-11e9-89ad-d58be75aeb6f": { - "id": "2ea7a050-6156-11e9-89ad-d58be75aeb6f", - "name": "2ea7a050-6156-11e9-89ad-d58be75aeb6f", - "macro": "EDGE", - "set": "Basic", - "dxfData": [], - "type": "EDGE" - }, - "a7c90920-d3f1-11e9-ad52-c581dcc5e148": { - "id": "a7c90920-d3f1-11e9-ad52-c581dcc5e148", - "name": "a7c90920-d3f1-11e9-ad52-c581dcc5e148", - "macro": "EDGE", - "set": "Basic", - "dxfData": [], - "type": "EDGE" - }, - "1643a8b0-d3f2-11e9-ad52-c581dcc5e148": { - "id": "1643a8b0-d3f2-11e9-ad52-c581dcc5e148", - "name": "Transition_3", - "macro": "Transition", - "set": "Basic", - "params": { "position": [30500, 40000], "cw1": 2000, "cw2": 900, "length": 10000, "rotation": 270, "height": 250 }, - "dxfData": [], - "type": "XY" - }, - "2e07a4b0-d3f2-11e9-ad52-c581dcc5e148": { - "id": "2e07a4b0-d3f2-11e9-ad52-c581dcc5e148", - "name": "Transition_4", - "macro": "Transition", - "set": "Basic", - "params": { "position": [110000, 40000], "cw1": 2000, "cw2": 900, "length": 10000, "rotation": 90, "height": 250 }, - "dxfData": [], - "type": "XY" - }, - "313eb3d0-d3f2-11e9-ad52-c581dcc5e148": { - "id": "313eb3d0-d3f2-11e9-ad52-c581dcc5e148", - "name": "Transition_5", - "macro": "Transition", - "set": "Basic", - "params": { "position": [60000, 70000], "cw1": 2000, "cw2": 800, "length": 10000, "rotation": 180, "height": 250 }, - "dxfData": [], - "type": "XY" - }, - "336b57d0-d3f2-11e9-ad52-c581dcc5e148": { - "id": "336b57d0-d3f2-11e9-ad52-c581dcc5e148", - "name": "Transition_6", - "macro": "Transition", - "set": "Basic", - "params": { "position": [60000, 10000], "cw1": 2000, "cw2": 800, "length": 10000, "height": 250 }, - "dxfData": [], - "type": "XY" - }, - "b6d50340-d628-11e9-9185-859b5727feb8": { - "id": "b6d50340-d628-11e9-9185-859b5727feb8", - "name": "New Feature", - "macro": "DropletGen", - "set": "Basic", - "referenceID": "b6d5c690-d628-11e9-9185-859b5727feb8", - "params": { - "position": [60000, 40000], - "orificeSize": 200, - "orificeLength": 400, - "oilInputWidth": 800, - "waterInputWidth": 600, - "outputWidth": 600, - "outputLength": 600, - "height": 250 - }, - "dxfData": [], - "type": "XY" - } - } - }, - { - "name": "control", - "color": "red", - "params": { "z_offset": 1200, "flip": true }, - "features": { - "2ea7a050-6156-11e9-89ad-d58be75aeb6f": { - "id": "2ea7a050-6156-11e9-89ad-d58be75aeb6f", - "name": "2ea7a050-6156-11e9-89ad-d58be75aeb6f", - "macro": "EDGE", - "set": "Basic", - "dxfData": [], - "type": "EDGE" - }, - "a7c90920-d3f1-11e9-ad52-c581dcc5e148": { - "id": "a7c90920-d3f1-11e9-ad52-c581dcc5e148", - "name": "a7c90920-d3f1-11e9-ad52-c581dcc5e148", - "macro": "EDGE", - "set": "Basic", - "dxfData": [], - "type": "EDGE" - } - } - }, - { - "name": "cells", - "color": "indigo", - "params": { "z_offset": 2000, "flip": false }, - "features": { - "2ea7a050-6156-11e9-89ad-d58be75aeb6f": { - "id": "2ea7a050-6156-11e9-89ad-d58be75aeb6f", - "name": "2ea7a050-6156-11e9-89ad-d58be75aeb6f", - "macro": "EDGE", - "set": "Basic", - "dxfData": [], - "type": "EDGE" - }, - "a7c90920-d3f1-11e9-ad52-c581dcc5e148": { - "id": "a7c90920-d3f1-11e9-ad52-c581dcc5e148", - "name": "a7c90920-d3f1-11e9-ad52-c581dcc5e148", - "macro": "EDGE", - "set": "Basic", - "dxfData": [], - "type": "EDGE" - } - } - } - ], - "version": 1, - "groups": [], - "customComponents": {} -} diff --git a/src/app/examples/jsonExamples.ts b/src/app/examples/jsonExamples.ts deleted file mode 100644 index 711576db..00000000 --- a/src/app/examples/jsonExamples.ts +++ /dev/null @@ -1,14 +0,0 @@ -export const example3 = - '{"name":"My Device","params":{"width":75800,"length":51000},"layers":[{"name":"flow","color":"indigo","params":{"z_offset":0,"flip":false},"features":{"97f1fd20-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f1fd20-3ea6-11e5-8298-1b576ed4eb08","name":"New Port","type":"Port","params":{"position":[30000,40000],"radius1":700,"radius2":700,"height":100}},"97f1fd21-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f1fd21-3ea6-11e5-8298-1b576ed4eb08","name":"New Port","type":"Port","params":{"position":[40000,40000],"radius1":700,"radius2":700,"height":100}},"97f22430-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f22430-3ea6-11e5-8298-1b576ed4eb08","name":"New Port","type":"Port","params":{"position":[50000,40000],"radius1":700,"radius2":700,"height":100}},"97f22431-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f22431-3ea6-11e5-8298-1b576ed4eb08","name":"New Port","type":"Port","params":{"position":[20000,40000],"radius1":700,"radius2":700,"height":100}},"97f22432-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f22432-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[20000,40000],"end":[20000,35000],"width":400,"height":100}},"97f22433-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f22433-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[20000,38000],"end":[17000,38000],"width":400,"height":100}},"97f22434-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f22434-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[17000,38000],"end":[17000,35000],"width":400,"height":100}},"97f22435-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f22435-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[20000,35000],"end":[20000,20000],"width":400,"height":100}},"97f22436-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f22436-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[20000,20000],"end":[10000,10000],"width":400,"height":100}},"97f22437-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f22437-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[17000,35000],"end":[15000,30000],"width":400,"height":100}},"97f22438-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f22438-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[15000,30000],"end":[10000,30000],"width":400,"height":100}},"97f22439-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f22439-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[10000,30000],"end":[10000,28000],"width":400,"height":100}},"97f2243a-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f2243a-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[10000,28000],"end":[15000,28000],"width":400,"height":100}},"97f2243b-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f2243b-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[15000,28000],"end":[15000,25000],"width":400,"height":100}},"97f2243c-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f2243c-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[15000,25000],"end":[8000,25000],"width":400,"height":100}},"97f2243d-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f2243d-3ea6-11e5-8298-1b576ed4eb08","name":"New Port","type":"Port","params":{"position":[8000,25000],"radius1":700,"radius2":700,"height":100}},"97f2243e-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f2243e-3ea6-11e5-8298-1b576ed4eb08","name":"New Port","type":"Port","params":{"position":[10000,10000],"radius1":700,"radius2":700,"height":100}},"97f2243f-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f2243f-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[30000,40000],"end":[30000,20000],"width":400,"height":100}},"97f22440-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f22440-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[30000,20000],"end":[20000,10000],"width":400,"height":100}},"97f22441-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f22441-3ea6-11e5-8298-1b576ed4eb08","name":"New Port","type":"Port","params":{"position":[20000,10000],"radius1":700,"radius2":700,"height":100}},"97f22442-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f22442-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[30000,38000],"end":[27000,38000],"width":400,"height":100}},"97f22443-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f22443-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[27000,38000],"end":[27000,30000],"width":400,"height":100}},"97f22444-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f22444-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[27000,30000],"end":[22000,30000],"width":400,"height":100}},"97f22445-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f22445-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[22000,30000],"end":[22000,28000],"width":400,"height":100}},"97f22446-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f22446-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[22000,28000],"end":[27000,28000],"width":400,"height":100}},"97f24b40-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f24b40-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[27000,28000],"end":[27000,26000],"width":400,"height":100}},"97f24b41-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f24b41-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[27000,26000],"end":[22000,26000],"width":400,"height":100}},"97f24b42-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f24b42-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[22000,26000],"end":[22000,24000],"width":400,"height":100}},"97f24b43-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f24b43-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[22000,24000],"end":[27000,24000],"width":400,"height":100}},"97f24b44-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f24b44-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[27000,24000],"end":[27000,22000],"width":400,"height":100}},"97f24b45-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f24b45-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[27000,22000],"end":[22000,22000],"width":400,"height":100}},"97f24b46-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f24b46-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[22000,22000],"end":[22000,20000],"width":400,"height":100}},"97f24b47-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f24b47-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[22000,20000],"end":[25000,20000],"width":400,"height":100}},"97f24b48-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f24b48-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[25000,20000],"end":[25000,17000],"width":400,"height":100}},"97f24b49-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f24b49-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[25000,17000],"end":[21000,17000],"width":400,"height":100}},"97f24b4a-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f24b4a-3ea6-11e5-8298-1b576ed4eb08","name":"New Port","type":"Port","params":{"position":[21000,17000],"radius1":700,"radius2":700,"height":100}},"97f24b4b-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f24b4b-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[40000,40000],"end":[40000,20000],"width":400,"height":100}},"97f24b4c-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f24b4c-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[40000,20000],"end":[50000,10000],"width":400,"height":100}},"97f24b4d-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f24b4d-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[40000,38000],"end":[43000,38000],"width":400,"height":100}},"97f24b4e-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f24b4e-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[43000,38000],"end":[43000,30000],"width":400,"height":100}},"97f24b4f-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f24b4f-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[43000,30000],"end":[48000,30000],"width":400,"height":100}},"97f24b50-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f24b50-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[48000,30000],"end":[48000,28000],"width":400,"height":100}},"97f24b51-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f24b51-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[48000,28000],"end":[43000,28000],"width":400,"height":100}},"97f24b52-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f24b52-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[43000,28000],"end":[43000,26000],"width":400,"height":100}},"97f24b53-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f24b53-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[43000,26000],"end":[48000,26000],"width":400,"height":100}},"97f24b54-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f24b54-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[48000,26000],"end":[48000,24000],"width":400,"height":100}},"97f24b55-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f24b55-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[48000,24000],"end":[43000,24000],"width":400,"height":100}},"97f24b56-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f24b56-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[43000,24000],"end":[43000,22000],"width":400,"height":100}},"97f24b57-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f24b57-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[43000,22000],"end":[48000,22000],"width":400,"height":100}},"97f24b58-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f24b58-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[48000,22000],"end":[48000,20000],"width":400,"height":100}},"97f24b59-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f24b59-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[48000,20000],"end":[45000,20000],"width":400,"height":100}},"97f24b5a-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f24b5a-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[45000,20000],"end":[45000,17000],"width":400,"height":100}},"97f24b5b-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f24b5b-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[45000,17000],"end":[49000,17000],"width":400,"height":100}},"97f24b5c-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f24b5c-3ea6-11e5-8298-1b576ed4eb08","name":"New Port","type":"Port","params":{"position":[50000,10000],"radius1":700,"radius2":700,"height":100}},"97f24b5d-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f24b5d-3ea6-11e5-8298-1b576ed4eb08","name":"New Port","type":"Port","params":{"position":[49000,17000],"radius1":700,"radius2":700,"height":100}},"97f24b5e-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f24b5e-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[50000,40000],"end":[50000,20000],"width":400,"height":100}},"97f24b5f-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f24b5f-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[50000,20000],"end":[60000,10000],"width":400,"height":100}},"97f24b60-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f24b60-3ea6-11e5-8298-1b576ed4eb08","name":"New Port","type":"Port","params":{"position":[60000,10000],"radius1":700,"radius2":700,"height":100}},"97f27250-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f27250-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[50000,38000],"end":[53000,38000],"width":400,"height":100}},"97f27251-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f27251-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[53000,38000],"end":[53000,35000],"width":400,"height":100}},"97f27252-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f27252-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[53000,35000],"end":[55000,30000],"width":400,"height":100}},"97f27253-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f27253-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[55000,30000],"end":[60000,30000],"width":400,"height":100}},"97f27254-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f27254-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[60000,30000],"end":[60000,28000],"width":400,"height":100}},"97f27255-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f27255-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[60000,28000],"end":[55000,28000],"width":400,"height":100}},"97f27256-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f27256-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[55000,28000],"end":[55000,25000],"width":400,"height":100}},"97f27257-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f27257-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[55000,25000],"end":[62000,25000],"width":400,"height":100}},"97f27258-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f27258-3ea6-11e5-8298-1b576ed4eb08","name":"New Port","type":"Port","params":{"position":[62000,25000],"radius1":700,"radius2":700,"height":100}},"97f27259-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f27259-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[15000,15000],"end":[15000,12000],"width":400,"height":100}},"97f2725a-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f2725a-3ea6-11e5-8298-1b576ed4eb08","name":"New Via","type":"Via","params":{"position":[15000,12000],"radius1":800,"radius2":700,"height":1100}},"97f2725b-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f2725b-3ea6-11e5-8298-1b576ed4eb08","name":"New Via","type":"Via","params":{"position":[26000,12000],"radius1":800,"radius2":700,"height":1100}},"97f2725c-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f2725c-3ea6-11e5-8298-1b576ed4eb08","name":"New Via","type":"Via","params":{"position":[44000,12000],"radius1":800,"radius2":700,"height":1100}},"97f2725d-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f2725d-3ea6-11e5-8298-1b576ed4eb08","name":"New Via","type":"Via","params":{"position":[55000,12000],"radius1":800,"radius2":700,"height":1100}},"97f2725e-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f2725e-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[55000,12000],"end":[55000,15000],"width":400,"height":100}},"97f2725f-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f2725f-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[26000,12000],"end":[30000,10000],"width":400,"height":100}},"97f27260-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f27260-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[44000,12000],"end":[40000,10000],"width":400,"height":100}},"97f27261-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f27261-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[40000,10000],"end":[38000,7000],"width":400,"height":100}},"97f27262-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f27262-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[30000,10000],"end":[32000,7000],"width":400,"height":100}},"97f27263-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f27263-3ea6-11e5-8298-1b576ed4eb08","name":"New Port","type":"Port","params":{"position":[32000,7000],"radius1":700,"radius2":700,"height":100}},"97f27264-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f27264-3ea6-11e5-8298-1b576ed4eb08","name":"New Port","type":"Port","params":{"position":[38000,7000],"radius1":700,"radius2":700,"height":100}},"97f27265-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f27265-3ea6-11e5-8298-1b576ed4eb08","name":"New CircleValve","type":"CircleValve","params":{"position":[35000,10000],"radius1":1400,"radius2":1200,"height":800}},"97f27266-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f27266-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[35000,10000],"end":[35000,30000],"width":400,"height":100}},"97f27267-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f27267-3ea6-11e5-8298-1b576ed4eb08","name":"New Port","type":"Port","params":{"position":[35000,30000],"radius1":700,"radius2":700,"height":100}},"97f27268-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f27268-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[35000,17000],"end":[38000,23000],"width":400,"height":100}},"97f27269-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f27269-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[38000,23000],"end":[36000,25000],"width":400,"height":100}},"97f2726a-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f2726a-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[36000,25000],"end":[35000,30000],"width":400,"height":100}},"97f2726b-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f2726b-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[35000,17000],"end":[32000,23000],"width":400,"height":100}},"97f2726c-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f2726c-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[32000,23000],"end":[34000,25000],"width":400,"height":100}},"97f2726d-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f2726d-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[34000,25000],"end":[35000,30000],"width":400,"height":100}},"97f2726e-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f2726e-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[32000,23000],"end":[35000,24000],"width":400,"height":100}},"97f2726f-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f2726f-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[38000,23000],"end":[35000,24000],"width":400,"height":100}},"97f27270-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f27270-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[25000,20000],"end":[28000,20000],"width":400,"height":100}},"97f27271-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f27271-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[28000,20000],"end":[28000,22000],"width":400,"height":100}},"97f27272-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f27272-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[28000,22000],"end":[27000,22000],"width":400,"height":100}},"97f27273-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f27273-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[45000,20000],"end":[42000,20000],"width":400,"height":100}},"97f27274-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f27274-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[42000,20000],"end":[42000,22000],"width":400,"height":100}},"97f27275-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f27275-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[42000,22000],"end":[44000,22000],"width":400,"height":100}},"97f27276-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f27276-3ea6-11e5-8298-1b576ed4eb08","name":"New Via","type":"Via","params":{"position":[35000,30000],"radius1":800,"radius2":700,"height":1100}},"97f27277-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f27277-3ea6-11e5-8298-1b576ed4eb08","name":"New Via","type":"Via","params":{"position":[32000,20000],"radius1":800,"radius2":700,"height":1100}},"97f27278-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f27278-3ea6-11e5-8298-1b576ed4eb08","name":"New Via","type":"Via","params":{"position":[38000,20000],"radius1":800,"radius2":700,"height":1100}},"a2de7790-3ea6-11e5-8298-1b576ed4eb08":{"id":"a2de7790-3ea6-11e5-8298-1b576ed4eb08","name":"New CircleValve","type":"CircleValve","params":{"position":[10000,20000],"radius1":1400,"radius2":1200,"height":800}},"a3d819d0-3ea6-11e5-8298-1b576ed4eb08":{"id":"a3d819d0-3ea6-11e5-8298-1b576ed4eb08","name":"New CircleValve","type":"CircleValve","params":{"position":[60000,20000],"radius1":1400,"radius2":1200,"height":800}}}},{"name":"control","color":"red","params":{"z_offset":1200,"flip":true},"features":{"97f27279-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f27279-3ea6-11e5-8298-1b576ed4eb08","name":"New CircleValve","type":"CircleValve","params":{"position":[20000,34000],"radius1":1400,"radius2":1200,"height":800}},"97f2727a-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f2727a-3ea6-11e5-8298-1b576ed4eb08","name":"New CircleValve","type":"CircleValve","params":{"position":[30000,34000],"radius1":1400,"radius2":1200,"height":800}},"97f2727b-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f2727b-3ea6-11e5-8298-1b576ed4eb08","name":"New CircleValve","type":"CircleValve","params":{"position":[40000,34000],"radius1":1400,"radius2":1200,"height":800}},"97f2727c-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f2727c-3ea6-11e5-8298-1b576ed4eb08","name":"New CircleValve","type":"CircleValve","params":{"position":[50000,34000],"radius1":1400,"radius2":1200,"height":800}},"97f2727d-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f2727d-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[20000,34000],"end":[24000,34000],"width":400,"height":100}},"97f2727e-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f2727e-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[24000,34000],"end":[24000,47000],"width":400,"height":100}},"97f29960-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f29960-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[30000,34000],"end":[34000,34000],"width":400,"height":100}},"97f29961-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f29961-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[34000,34000],"end":[34000,47000],"width":400,"height":100}},"97f29962-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f29962-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[40000,34000],"end":[37000,34000],"width":400,"height":100}},"97f29963-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f29963-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[37000,34000],"end":[36000,34000],"width":400,"height":100}},"97f29964-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f29964-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[36000,34000],"end":[36000,47000],"width":400,"height":100}},"97f29965-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f29965-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[50000,34000],"end":[46000,34000],"width":400,"height":100}},"97f29966-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f29966-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[46000,34000],"end":[46000,47000],"width":400,"height":100}},"97f29967-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f29967-3ea6-11e5-8298-1b576ed4eb08","name":"New Port","type":"Port","params":{"position":[24000,47000],"radius1":700,"radius2":700,"height":100}},"97f29968-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f29968-3ea6-11e5-8298-1b576ed4eb08","name":"New Port","type":"Port","params":{"position":[34000,47000],"radius1":700,"radius2":700,"height":100}},"97f29969-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f29969-3ea6-11e5-8298-1b576ed4eb08","name":"New Port","type":"Port","params":{"position":[36000,47000],"radius1":700,"radius2":700,"height":100}},"97f2996a-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f2996a-3ea6-11e5-8298-1b576ed4eb08","name":"New Port","type":"Port","params":{"position":[46000,47000],"radius1":700,"radius2":700,"height":100}},"97f2996b-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f2996b-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[15000,12000],"end":[26000,12000],"width":400,"height":100}},"97f2996c-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f2996c-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[44000,12000],"end":[55000,12000],"width":400,"height":100}},"97f2996d-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f2996d-3ea6-11e5-8298-1b576ed4eb08","name":"New Port","type":"Port","params":{"position":[15000,12000],"radius1":700,"radius2":700,"height":100}},"97f2996e-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f2996e-3ea6-11e5-8298-1b576ed4eb08","name":"New Port","type":"Port","params":{"position":[26000,12000],"radius1":700,"radius2":700,"height":100}},"97f2996f-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f2996f-3ea6-11e5-8298-1b576ed4eb08","name":"New Port","type":"Port","params":{"position":[44000,12000],"radius1":700,"radius2":700,"height":100}},"97f29970-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f29970-3ea6-11e5-8298-1b576ed4eb08","name":"New Port","type":"Port","params":{"position":[55000,12000],"radius1":700,"radius2":700,"height":100}},"97f29971-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f29971-3ea6-11e5-8298-1b576ed4eb08","name":"New Port","type":"Port","params":{"position":[25000,21000],"radius1":700,"radius2":700,"height":100}},"97f29972-3ea6-11e5-8298-1b576ed4eb08":{"id":"97f29972-3ea6-11e5-8298-1b576ed4eb08","name":"New Port","type":"Port","params":{"position":[45000,21000],"radius1":700,"radius2":700,"height":100}},"a54e6620-3ea6-11e5-8298-1b576ed4eb08":{"id":"a54e6620-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[10000,20000],"end":[15000,12000],"width":400,"height":100}},"a63ff210-3ea6-11e5-8298-1b576ed4eb08":{"id":"a63ff210-3ea6-11e5-8298-1b576ed4eb08","name":"New Channel","type":"Channel","params":{"start":[55000,12000],"end":[60000,20000],"width":400,"height":100}},"a7efc4f0-3ea6-11e5-8298-1b576ed4eb08":{"id":"a7efc4f0-3ea6-11e5-8298-1b576ed4eb08","name":"New Port","type":"Port","params":{"position":[10000,20000],"radius1":700,"radius2":700,"height":100}},"a8879820-3ea6-11e5-8298-1b576ed4eb08":{"id":"a8879820-3ea6-11e5-8298-1b576ed4eb08","name":"New Port","type":"Port","params":{"position":[60000,20000],"radius1":700,"radius2":700,"height":100}}}}],"groups":[],"defaults":{}}'; - -export const example1 = - '{"name":"My Other Device","params":{"width":135000,"length":85000},"layers":[{"name":"flow","color":"indigo","params":{"z_offset":0,"flip":false},"features":{"7d4dce00-4f92-11e7-b516-0963e7d642b6":{"id":"7d4dce00-4f92-11e7-b516-0963e7d642b6","name":"New Feature","type":"Channel","set":"Basic","params":{"start":[0,0],"end":[135000,0],"channelWidth":800,"height":100}},"802dbc70-4f92-11e7-b516-0963e7d642b6":{"id":"802dbc70-4f92-11e7-b516-0963e7d642b6","name":"New Feature","type":"Channel","set":"Basic","params":{"start":[135000,0],"end":[135000,85000],"channelWidth":800,"height":100}},"84122290-4f92-11e7-b516-0963e7d642b6":{"id":"84122290-4f92-11e7-b516-0963e7d642b6","name":"New Feature","type":"Channel","set":"Basic","params":{"start":[135000,85000],"end":[0,85000],"channelWidth":800,"height":100}},"8791ac60-4f92-11e7-b516-0963e7d642b6":{"id":"8791ac60-4f92-11e7-b516-0963e7d642b6","name":"New Feature","type":"Channel","set":"Basic","params":{"start":[0,85000],"end":[0,0],"channelWidth":800,"height":100}}}},{"name":"control","color":"red","params":{"z_offset":1200,"flip":true},"features":{"a937dec0-4f92-11e7-b516-0963e7d642b6":{"id":"a937dec0-4f92-11e7-b516-0963e7d642b6","name":"New Feature","type":"Channel","set":"Basic","params":{"start":[0,0],"end":[0,85000],"channelWidth":800,"height":100}},"ab87e940-4f92-11e7-b516-0963e7d642b6":{"id":"ab87e940-4f92-11e7-b516-0963e7d642b6","name":"New Feature","type":"Channel","set":"Basic","params":{"start":[0,85000],"end":[135000,85000],"channelWidth":800,"height":100}},"ad94f750-4f92-11e7-b516-0963e7d642b6":{"id":"ad94f750-4f92-11e7-b516-0963e7d642b6","name":"New Feature","type":"Channel","set":"Basic","params":{"start":[135000,85000],"end":[135000,0],"channelWidth":800,"height":100}},"af694220-4f92-11e7-b516-0963e7d642b6":{"id":"af694220-4f92-11e7-b516-0963e7d642b6","name":"New Feature","type":"Channel","set":"Basic","params":{"start":[135000,0],"end":[0,0],"channelWidth":800,"height":100}}}}],"groups":[]}'; - -export const UpdatedExample = - '{"name":"My Other Device","params":{"width":135000,"length":85000},"renderLayers":[{"id":"d51fc900-e923-11ec-baa7-bf96f82ad573","name":"RenderLayerFlow_1","modellayer":"4952d7a0-f16c-11eb-8c04-ff751cb31c4c","type":"FLOW","features":[],"color":"indigo"},{"id":"d51fc901-e923-11ec-baa7-bf96f82ad573","name":"RenderLayerControl_1","modellayer":"4952feb0-f16c-11eb-8c04-ff751cb31c4c","type":"CONTROL","features":[],"color":"red"},{"id":"d51fc902-e923-11ec-baa7-bf96f82ad573","name":"RenderLayerIntegration_1","modellayer":"4952feb1-f16c-11eb-8c04-ff751cb31c4c","type":"INTEGRATION","features":[],"color":"green"}],"layers":[{"id":"4952d7a0-f16c-11eb-8c04-ff751cb31c4c","name":"LayerFlow_1","type":"FLOW","group":"0","params":{"z_offset":0,"flip":false},"features":[]},{"id":"4952feb0-f16c-11eb-8c04-ff751cb31c4c","name":"LayerControl_1","type":"CONTROL","group":"0","params":{"z_offset":0,"flip":false},"features":[]},{"id":"4952feb1-f16c-11eb-8c04-ff751cb31c4c","name":"LayerIntegration_1","type":"INTEGRATION","group":"0","params":{"z_offset":0,"flip":false},"features":[]}],"groups":[],"components":[],"connections":[],"valves":[],"version":"1.2"}'; - -export const dafdtemplate = - '{"name":"DAFD Template","params":{"width":70000,"length":70000},"components":[{"id":"e958b4d0-6155-11e9-89ad-d58be75aeb6f","name":"Port_in","entity":"PORT","params":{"position":[10000,35000],"portRadius":1998,"height":1100},"xspan":3996,"yspan":3996,"ports":[]},{"id":"eadf7be0-6155-11e9-89ad-d58be75aeb6f","name":"Port_out","entity":"PORT","params":{"position":[60000,35000],"portRadius":1998,"height":1100},"xspan":3996,"yspan":3996,"ports":[]},{"id":"ec125690-6155-11e9-89ad-d58be75aeb6f","name":"Port_oil1","entity":"PORT","params":{"position":[35075,10000],"portRadius":1998,"height":1100},"xspan":3996,"yspan":3996,"ports":[]},{"id":"f0839360-6155-11e9-89ad-d58be75aeb6f","name":"Port_oil2","entity":"PORT","params":{"position":[35075,60000],"portRadius":1998,"height":1100},"xspan":3996,"yspan":3996,"ports":[]},{"id":"b6d5c690-d628-11e9-9185-859b5727feb8","name":"DropletGen_1","entity":"NOZZLE DROPLET GENERATOR","params":{"position":[40000,35000],"orificeSize":75,"orificeLength":75,"oilInputWidth":150,"waterInputWidth":150,"outputWidth":150,"outputLength":5000,"height":75},"xspan":5225,"yspan":150,"ports":[{"x":75,"y":-75,"layer":"FLOW","label":"1"},{"x":5225,"y":0,"layer":"FLOW","label":"2"},{"x":75,"y":75,"layer":"FLOW","label":"3"},{"x":0,"y":0,"layer":"FLOW","label":"4"}]}],"connections":[],"features":[{"name":"flow","color":"indigo","params":{"z_offset":0,"flip":false},"features":{"e957f180-6155-11e9-89ad-d58be75aeb6f":{"id":"e957f180-6155-11e9-89ad-d58be75aeb6f","name":"New Feature","macro":"Port","set":"Basic","referenceID":"e958b4d0-6155-11e9-89ad-d58be75aeb6f","params":{"position":[10000,35000],"portRadius":1998,"height":1100},"dxfData":[],"type":"XY"},"eadf06b0-6155-11e9-89ad-d58be75aeb6f":{"id":"eadf06b0-6155-11e9-89ad-d58be75aeb6f","name":"New Feature","macro":"Port","set":"Basic","referenceID":"eadf7be0-6155-11e9-89ad-d58be75aeb6f","params":{"position":[60000,35000],"portRadius":1998,"height":1100},"dxfData":[],"type":"XY"},"ec119340-6155-11e9-89ad-d58be75aeb6f":{"id":"ec119340-6155-11e9-89ad-d58be75aeb6f","name":"New Feature","macro":"Port","set":"Basic","referenceID":"ec125690-6155-11e9-89ad-d58be75aeb6f","params":{"position":[35075,10000],"portRadius":1998,"height":1100},"dxfData":[],"type":"XY"},"f082f720-6155-11e9-89ad-d58be75aeb6f":{"id":"f082f720-6155-11e9-89ad-d58be75aeb6f","name":"New Feature","macro":"Port","set":"Basic","referenceID":"f0839360-6155-11e9-89ad-d58be75aeb6f","params":{"position":[35075,60000],"portRadius":1998,"height":1100},"dxfData":[],"type":"XY"},"1643a8b0-d3f2-11e9-ad52-c581dcc5e148":{"id":"1643a8b0-d3f2-11e9-ad52-c581dcc5e148","name":"Transition_3","macro":"Transition","set":"Basic","params":{"position":[10000,35000],"cw1":2000,"cw2":150,"length":10000,"rotation":270,"height":250},"dxfData":[],"type":"XY"},"2e07a4b0-d3f2-11e9-ad52-c581dcc5e148":{"id":"2e07a4b0-d3f2-11e9-ad52-c581dcc5e148","name":"Transition_4","macro":"Transition","set":"Basic","params":{"position":[60000,35000],"cw1":2000,"cw2":150,"length":10000,"rotation":90,"height":250},"dxfData":[],"type":"XY"},"313eb3d0-d3f2-11e9-ad52-c581dcc5e148":{"id":"313eb3d0-d3f2-11e9-ad52-c581dcc5e148","name":"Transition_5","macro":"Transition","set":"Basic","params":{"position":[35075,60000],"cw1":2000,"cw2":150,"length":10000,"rotation":180,"height":250},"dxfData":[],"type":"XY"},"336b57d0-d3f2-11e9-ad52-c581dcc5e148":{"id":"336b57d0-d3f2-11e9-ad52-c581dcc5e148","name":"Transition_6","macro":"Transition","set":"Basic","params":{"position":[35075,10000],"cw1":2000,"cw2":150,"length":10000,"height":250},"dxfData":[],"type":"XY"},"b6d50340-d628-11e9-9185-859b5727feb8":{"id":"b6d50340-d628-11e9-9185-859b5727feb8","name":"New Feature","macro":"DropletGen","set":"Basic","referenceID":"b6d5c690-d628-11e9-9185-859b5727feb8","params":{"position":[40000,35000],"orificeSize":75,"orificeLength":75,"oilInputWidth":150,"waterInputWidth":150,"outputWidth":150,"outputLength":5000,"height":75},"dxfData":[],"type":"XY"},"e1a50cd0-f506-11e9-b6c5-c5f0545f0b4a":{"id":"e1a50cd0-f506-11e9-b6c5-c5f0545f0b4a","name":"e1a50cd0-f506-11e9-b6c5-c5f0545f0b4a","macro":"EDGE","set":"Basic","dxfData":[],"type":"EDGE"},"48225b40-f50a-11e9-a170-c3e417364f96":{"id":"48225b40-f50a-11e9-a170-c3e417364f96","name":"48225b40-f50a-11e9-a170-c3e417364f96","macro":"EDGE","set":"Basic","dxfData":[],"type":"EDGE"}}},{"name":"control","color":"red","params":{"z_offset":1200,"flip":true},"features":{"e1a50cd0-f506-11e9-b6c5-c5f0545f0b4a":{"id":"e1a50cd0-f506-11e9-b6c5-c5f0545f0b4a","name":"e1a50cd0-f506-11e9-b6c5-c5f0545f0b4a","macro":"EDGE","set":"Basic","dxfData":[],"type":"EDGE"},"48225b40-f50a-11e9-a170-c3e417364f96":{"id":"48225b40-f50a-11e9-a170-c3e417364f96","name":"48225b40-f50a-11e9-a170-c3e417364f96","macro":"EDGE","set":"Basic","dxfData":[],"type":"EDGE"}}},{"name":"cells","color":"indigo","params":{"z_offset":2000,"flip":false},"features":{"e1a50cd0-f506-11e9-b6c5-c5f0545f0b4a":{"id":"e1a50cd0-f506-11e9-b6c5-c5f0545f0b4a","name":"e1a50cd0-f506-11e9-b6c5-c5f0545f0b4a","macro":"EDGE","set":"Basic","dxfData":[],"type":"EDGE"},"48225b40-f50a-11e9-a170-c3e417364f96":{"id":"48225b40-f50a-11e9-a170-c3e417364f96","name":"48225b40-f50a-11e9-a170-c3e417364f96","macro":"EDGE","set":"Basic","dxfData":[],"type":"EDGE"}}}],"version":"1.2","groups":[],"customComponents":{}}'; - -const Examples = { example1, example2: UpdatedExample, example3 }; -export default Examples; diff --git a/src/app/geometry/geometryEdge.ts b/src/app/geometry/geometryEdge.ts deleted file mode 100644 index 8a3a3618..00000000 --- a/src/app/geometry/geometryEdge.ts +++ /dev/null @@ -1,39 +0,0 @@ -export default class GeometryEdge { - private __start: any; - private __end: any; - private __type: any; - private __id: any; - private __dxfData: any; - - constructor(start: any, end: any, type: any, id: any, data: any) { - this.__start = start; - this.__end = end; - - this.__type = type; - this.__id = id; - - this.__dxfData = data; - - // TODO: Do classification of kind of edge (curve, horizontal, vertical, angled, etc), compute length - } - - get id() { - return this.__id; - } - - get start() { - return this.__start; - } - - get end() { - return this.__end; - } - - get type() { - return this.__type; - } - - get dxfData() { - return this.__dxfData; - } -} diff --git a/src/app/geometry/geometryGraph.ts b/src/app/geometry/geometryGraph.ts deleted file mode 100644 index 4fb0d31d..00000000 --- a/src/app/geometry/geometryGraph.ts +++ /dev/null @@ -1,189 +0,0 @@ -import GeometryEdge from "./geometryEdge"; - -// @ts-ignore -import graphlib from "@dagrejs/graphlib"; -import paper from "paper"; - -export default class GeometryGraph { - private __nodes: any; - private __nodecount: number; - private __edgecount: number; - private __edgeData: Map; - private __networkGraph: any; - - constructor() { - // TODO: Do all the initializations here - this.__nodes = new Map(); - this.__nodecount = 0; - this.__edgecount = 0; - this.__edgeData = new Map(); - - this.__networkGraph = new graphlib.Graph({ directed: false }); - } - - addEdge(start: any, end: any, data: any): void { - const startnode = this.findNode(start); - const endnode = this.findNode(end); - - const edgeobject = new GeometryEdge(startnode, endnode, data.type, String(this.__edgecount++), data); - - this.__edgeData.set(edgeobject.id, edgeobject); - - this.__networkGraph.setEdge(startnode, endnode, edgeobject.id); - } - - findNode(node: any) { - for (const key of this.__nodes.keys()) { - const nodetocheck = this.__nodes.get(key); - - if (GeometryGraph.computeDistance(node, nodetocheck) < 0.000001) { - return key; - } - } - - // If it comes to this, then it means that the node does not exist - const newkey = String(this.__nodecount++); - this.__nodes.set(newkey, node); - - return newkey; - } - - generateGeometry() { - // console.log("Cycles:", graphlib.alg.findCycles(this.__networkGraph)); - // console.log("Edges:", this.__networkGraph.edges()); - // console.log("Nodes:", this.__nodes); - // console.log("Edge Data:", this.__edgeData); - const path = new paper.CompoundPath(""); - - // graphlib.alg.findCycles(this.__networkGraph); - const graphcomponents = graphlib.alg.components(this.__networkGraph); - // console.log("Components:", graphcomponents); - - /* - Step 1 - Iterate through each of the components (disconnected components) - Step 2 - Draw outline for each of the components - */ - - for (const component of graphcomponents) { - this.drawComponent(component, path); - } - - return path; - } - - drawComponent(component: any[], path: any): void { - /* - Step 1 - Take the starting node - Step 2 - start traversing through the component and start making a path with segments - */ - - // console.log("Graph component",component); - - // Get the first item in the component - - // let startnode = this.__nodes.get(component[0]); - // console.log("startnode", startnode); - - const segments = []; - const startnode = this.__nodes.get(component[0]); - const endnode = null; - // console.log("test ?"); - // Get traversal - const traversal = graphlib.alg.preorder(this.__networkGraph, component[0]); - - const childpath = new paper.Path(); - - for (let i = 0; i < traversal.length; i++) { - const noderef = traversal[i]; - const node = this.__nodes.get(noderef); - let nextnoderef; - if (i + 1 === traversal.length) { - // Last Node - nextnoderef = traversal[0]; - } else { - // All other nodes - nextnoderef = traversal[i + 1]; - } - - // Get the edge - const edge = this.__getEdge(noderef, nextnoderef); - - // console.log("Edge:", edge); - // console.log("Edge Type:", edge.type); - switch (edge.type) { - case "LINE": - childpath.add(new paper.Point(node.x, node.y)); - break; - case "ARC": - childpath.add(new paper.Point(node.x, node.y)); - const nextnode = this.__nodes.get(nextnoderef); - const endpoint = new paper.Point(nextnode.x, nextnode.y); - const midpoint = this.getARCMidpoint(edge.dxfData); - childpath.arcTo(midpoint, endpoint); - break; - } - } - - path.addChild(childpath); - - // //Generate Lines for everything - // for(let i = 0; i< traversal.length; i++ ){ - // let node = this.__nodes.get(traversal[i]); - // - // console.log("Line:", "Start", startnode, "End" , endnode); - // //TODO: Draw curve for curves - // let line = new paper.Path.Line(new paper.Point(startnode.x, endnode.y), new paper.Point(endnode.x, endnode.y)); - // childpath.add(line); - // } - // - // startnode = endnode; - // endnode = this.__nodes.get(component[0]); - // console.log("Line:", "Start", startnode, "End" , endnode); - // - // //Last segment to close everything off - // childpath.add(new paper.Path.Line( - // // new paper.Point(startnode.x, endnode.y), - // new paper.Point(endnode.x, endnode.y)) - // ); - // - // console.log(path); - - // Now join all the segments - // let joinedpath = null; - // for(let i = 0; i < segments.length; i++){ - // if(joinedpath === null){ - // joinedpath = segments[i]; - // } - // joinedpath.join(segments[i]); - // } - - // console.log("Joined Path", joinedpath); - // console.log("Segments:", segments); - - // path.addChild(joinedpath); - } - - getARCMidpoint(dxfData: any) { - // console.log("DXF:",dxfData); - const center = new paper.Point(dxfData.center.x, dxfData.center.y); - const radius = dxfData.radius; - const startAngle = dxfData.startAngle; - const endAngle = dxfData.endAngle; //* 180/Math.PI; - const midAngle = (startAngle + endAngle) / 2; - - const midpoint = new paper.Point(center.x + radius * Math.cos(midAngle), center.y + radius * Math.sin(midAngle)); - - return midpoint; - } - - __getEdge(source: any, target: any) { - const edgeref = this.__networkGraph.edge(source, target); - return this.__edgeData.get(edgeref); - } - - static computeDistance(node: any, nodetocheck: any): number { - const sqdist = Math.pow(node.x - nodetocheck.x, 2) + Math.pow(node.y - nodetocheck.y, 2); - // TODO: check if there is a z component - return Math.sqrt(sqdist); - } -} diff --git a/src/app/index.ts b/src/app/index.ts deleted file mode 100644 index fb69f94c..00000000 --- a/src/app/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -import PaperView from "./view/paperView"; -import AdaptiveGrid from "./view/grid/adaptiveGrid"; -import Device from "./core/device"; -import ViewManager from "./view/viewManager"; - -import * as Examples from "./examples/jsonExamples"; - -import Registry from "./core/registry"; - -export { Registry, PaperView, AdaptiveGrid, Device, ViewManager, Examples }; diff --git a/src/app/library/alignmentMarks.ts b/src/app/library/alignmentMarks.ts deleted file mode 100644 index 8882e880..00000000 --- a/src/app/library/alignmentMarks.ts +++ /dev/null @@ -1,178 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import { ToolPaperObject } from "../core/init"; - -interface ParamsIF { - position: number[]; - width: number; - length: number; - color: paper.Color; -} - -export default class AlignmentMarks extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - width: "Float", - length: "Float", - height: "Float" - }; - - this.__defaults = { - width: 4000, - length: 4000, - height: 250 - }; - - this.__units = { - width: "μm", - length: "μm", - height: "μm" - }; - - this.__minimum = { - width: 10, - length: 10, - height: 10 - }; - - this.__maximum = { - width: 200000, - length: 200000, - height: 1200 - }; - - this.__placementTool = "multilayerPositionTool"; - - this.__toolParams = { - position: "position" - }; - - this.__featureParams = { - position: "position", - width: "width", - length: "length" - }; - - this.__targetParams = { - width: "width", - length: "length" - }; - - this.__renderKeys = ["FLOW", "CONTROL"]; - - this.__mint = "ALIGNMENT MARKS"; - - this.__zOffsetKeys = { - FLOW: "height", - CONTROL: "height" - }; - - this.__substrateOffset = { - FLOW: "0", - CONTROL: "+1" - }; - } - - render2D(params: ParamsIF, key: string) { - if (key === "FLOW") { - return this.__drawFlow(params); - } else if (key === "CONTROL") { - return this.__drawControl(params); - } - - throw new Error("Unknown key: " + key); - } - - render2DTarget(key: string | null, params: ParamsIF): paper.CompoundPath { - const position = params.position; - const width = params.width; - const length = params.length; - const color = params.color; - const center = new paper.Point(position[0], position[1]); - const ret = new paper.CompoundPath(""); - const topleftpoint = new paper.Point(position[0] - width, position[1] - length); - const bottomrightpoint = new paper.Point(position[0] + width, position[1] + length); - - const topleftrect = new paper.Path.Rectangle(topleftpoint, center); - - ret.addChild(topleftrect); - - const bottomrightrect = new paper.Path.Rectangle((position as unknown) as paper.Rectangle, (bottomrightpoint as unknown) as paper.Size); - - ret.addChild(bottomrightrect); - - const topmiddlepoint = new paper.Point(position[0], position[1] - length); - const middlerightpoint = new paper.Point(position[0] + width, position[1]); - const middleleftpoint = new paper.Point(position[0] - width, position[1]); - const bottommiddlepoint = new paper.Point(position[0], position[1] + length); - - const toprightrect = new paper.Path.Rectangle(topmiddlepoint, middlerightpoint); - - ret.addChild(toprightrect); - - const bottomleftrect = new paper.Path.Rectangle(middleleftpoint, bottommiddlepoint); - - ret.addChild(bottomleftrect); - - ret.fillColor = color; - - ret.fillColor.alpha = 0.5; - - return ret; - } - - __drawFlow(params: ParamsIF) { - const position = params.position; - const width = params.width; - const length = params.length; - const color = params.color; - const center = new paper.Point(position[0], position[1]); - const ret = new paper.CompoundPath(""); - const topleftpoint = new paper.Point(position[0] - width, position[1] - length); - const bottomrightpoint = new paper.Point(position[0] + width, position[1] + length); - - const topleftrect = new paper.Path.Rectangle(topleftpoint, center); - - ret.addChild(topleftrect); - - const bottomrightrect = new paper.Path.Rectangle((position as unknown) as paper.Rectangle, (bottomrightpoint as unknown) as paper.Size); - - ret.addChild(bottomrightrect); - - ret.fillColor = color; - return ret; - } - - __drawControl(params: ParamsIF) { - const position = params.position; - const width = params.width; - const length = params.length; - const color = params.color; - const here = new paper.Point(position[0], position[1]); - const ret = new paper.CompoundPath(""); - const topmiddlepoint = new paper.Point(position[0], position[1] - length); - const middlerightpoint = new paper.Point(position[0] + width, position[1]); - const middleleftpoint = new paper.Point(position[0] - width, position[1]); - const bottommiddlepoint = new paper.Point(position[0], position[1] + length); - - const toprightrect = new paper.Path.Rectangle(topmiddlepoint, middlerightpoint); - - ret.addChild(toprightrect); - - const bottomleftrect = new paper.Path.Rectangle(middleleftpoint, bottommiddlepoint); - - ret.addChild(bottomleftrect); - - ret.fillColor = color; - return ret; - } -} diff --git a/src/app/library/anode.ts b/src/app/library/anode.ts deleted file mode 100644 index c379cd5b..00000000 --- a/src/app/library/anode.ts +++ /dev/null @@ -1,122 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class Anode extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - anodeRadius: "Float", - pegHeight: "Float", - pegWidth: "Float", - height: "Float", - rotation: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - anodeRadius: 0.9 * 1000, - pegHeight: 0.2 * 1000, - pegWidth: 0.7 * 1000, - height: 1.1 * 1000, - rotation: 0 - }; - - this.__units = { - componentSpacing: "μm", - anodeRadius: "μm", - pegHeight: "μm", - pegWidth: "μm", - height: "μm", - rotation: "°" - }; - - this.__minimum = { - componentSpacing: 0, - anodeRadius: 0.4 * 10, - pegHeight: 0.1 * 1000, - pegWidth: 0.1 * 1000, - height: 10, - rotation: 0 - }; - - this.__maximum = { - componentSpacing: 10000, - anodeRadius: 2000, - pegHeight: 2 * 1000, - pegWidth: 2 * 1000, - height: 1200, - rotation: 90 - }; - - this.__placementTool = "componentPositionTool"; - - this.__toolParams = { - position: "position" - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - anodeRadius: "anodeRadius", - pegHeight: "pegHeight", - pegWidth: "pegWidth", - rotation: "rotation" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - anodeRadius: "anodeRadius", - pegHeight: "pegHeight", - pegWidth: "pegWidth", - rotation: "rotation" - }; - - this.__renderKeys = ["FLOW"]; - - this.__mint = "ANODE"; - } - - render2D(params: { [k: string]: any }, key: string): paper.PathItem { - // Regardless of the key... - const position = params.position; - const radius = params.anodeRadius; - const pegheight = params.pegHeight; - const pegwidth = params.pegWidth; - const rotation = params.rotation; - const color1 = params.color; - const pos = new paper.Point(position[0], position[1]); - const outerCircle = new paper.Path.Circle(pos, radius); - outerCircle.fillColor = color1; - - const peg = new paper.Path.Rectangle(new paper.Rectangle(position[0] - pegwidth / 2, position[1] - pegheight / 2, pegwidth, pegheight)); - const finalCircle = outerCircle.subtract(peg); - finalCircle.fillColor = color1; - outerCircle.remove(); - peg.remove(); - return (finalCircle.rotate(rotation, pos) as unknown) as paper.PathItem; - } - - render2DTarget(key: string | null, params: { [k: string]: any }): paper.PathItem { - const render = this.render2D(params, key!); - render.fillColor!.alpha = 0.5; - return render; - } - - getPorts(params: any) { - const ports = []; - - ports.push(new ComponentPort(0, 0, "1", LogicalLayerType.FLOW)); - - return ports; - } -} diff --git a/src/app/library/betterMixer.ts b/src/app/library/betterMixer.ts deleted file mode 100644 index d120a39d..00000000 --- a/src/app/library/betterMixer.ts +++ /dev/null @@ -1,163 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class BetterMixer extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - bendSpacing: "Float", - numberOfBends: "Float", - channelWidth: "Float", - bendLength: "Float", - rotation: "Float", - height: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - channelWidth: 0.8 * 1000, - bendSpacing: 1.23 * 1000, - numberOfBends: 1, - rotation: 0, - bendLength: 2.46 * 1000, - height: 250 - }; - - this.__units = { - componentSpacing: "μm", - bendSpacing: "μm", - numberOfBends: "", - channelWidth: "μm", - bendLength: "μm", - rotation: "°", - height: "μm" - }; - - this.__minimum = { - componentSpacing: 0, - channelWidth: 10, - bendSpacing: 10, - numberOfBends: 1, - rotation: 0, - bendLength: 10, - height: 10 - }; - - this.__maximum = { - componentSpacing: 10000, - channelWidth: 2000, - bendSpacing: 6000, - numberOfBends: 20, - rotation: 360, - bendLength: 12 * 1000, - height: 1200 - }; - - this.__placementTool = "componentPositionTool"; - - this.__toolParams = { - cursorPosition: "position" - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - channelWidth: "channelWidth", - bendSpacing: "bendSpacing", - numberOfBends: "numberOfBends", - rotation: "rotation", - bendLength: "bendLength" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - channelWidth: "channelWidth", - bendSpacing: "bendSpacing", - numberOfBends: "numberOfBends", - rotation: "rotation", - bendLength: "bendLength" - }; - - this.__renderKeys = ["FLOW"]; - - this.__mint = "MIXER"; - - this.__zOffsetKeys = { - FLOW: "height" - }; - - this.__substrateOffset = { - FLOW: "0" - }; - } - - getPorts(params: { [k: string]: any }) { - const channelWidth = params.channelWidth; - const bendLength = params.bendLength; - const bendSpacing = params.bendSpacing; - const rotation = params.rotation; - const numberOfBends = params.numberOfBends; - - const ports = []; - - ports.push(new ComponentPort(bendLength / 2 + channelWidth, 0, "1", LogicalLayerType.FLOW)); - - ports.push(new ComponentPort(bendLength / 2 + channelWidth, (2 * numberOfBends + 1) * channelWidth + 2 * numberOfBends * bendSpacing, "2", LogicalLayerType.FLOW)); - - return ports; - } - - render2D(params: { [k: string]: any }, key: string): paper.CompoundPath { - const channelWidth = params.channelWidth; - const bendLength = params.bendLength; - const bendSpacing = params.bendSpacing; - const rotation = params.rotation; - const numBends = params.numberOfBends; - const x = params.position[0]; - const y = params.position[1]; - const color = params.color; - const segHalf = bendLength / 2 + channelWidth; - const segLength = bendLength + 2 * channelWidth; - const segBend = bendSpacing + 2 * channelWidth; - const vRepeat = 2 * bendSpacing + 2 * channelWidth; - const vOffset = bendSpacing + channelWidth; - const hOffset = bendLength / 2 + channelWidth / 2; - const serp = new paper.CompoundPath(""); - // draw first segment - serp.addChild(new paper.Path.Rectangle(new paper.Rectangle(x, y, segHalf + channelWidth / 2, channelWidth))); - for (let i = 0; i < numBends; i++) { - serp.addChild(new paper.Path.Rectangle(new paper.Rectangle(x, y + vRepeat * i, channelWidth, segBend))); - serp.addChild(new paper.Path.Rectangle(new paper.Rectangle(x, y + vOffset + vRepeat * i, segLength, channelWidth))); - serp.addChild(new paper.Path.Rectangle(new paper.Rectangle(x + channelWidth + bendLength, y + vOffset + vRepeat * i, channelWidth, segBend))); - if (i === numBends - 1) { - // draw half segment to close - serp.addChild(new paper.Path.Rectangle(new paper.Rectangle(x + hOffset, y + vRepeat * (i + 1), segHalf, channelWidth))); - } else { - // draw full segment - serp.addChild(new paper.Path.Rectangle(new paper.Rectangle(x, y + vRepeat * (i + 1), segLength, channelWidth))); - } - } - - serp.fillColor = color; - return (serp.rotate(rotation, new paper.Point(x, y)) as unknown) as paper.CompoundPath; - } - - render2DTarget(key: string | null, params: { [k: string]: any }): paper.CompoundPath { - if (key === null) { - key = this.__renderKeys[0]; - } - const serp = this.render2D(params, key); - serp.fillColor!.alpha = 0.5; - return serp; - } -} diff --git a/src/app/library/capacitancesensor.ts b/src/app/library/capacitancesensor.ts deleted file mode 100644 index c9a075b0..00000000 --- a/src/app/library/capacitancesensor.ts +++ /dev/null @@ -1,240 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class CapacitanceSensor extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - rotation: "Float", - height: "Float", - inletWidth: "Float", - inletLength: "Float", - electrodeWidth: "Float", - electrodeLength: "Float", - electrodeDistance: "Float", - sensorWidth: "Float", - sensorLength: "Float", - channelDepth: "Float", - electrodeDepth: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - rotation: 0, - height: 250, - inletWidth: 1 * 1000, - inletLength: 10 * 1000, - electrodeWidth: 1.5 * 1000, - electrodeLength: 4 * 1000, - electrodeDistance: 2 * 1000, - sensorWidth: 1 * 1000, - sensorLength: 3 * 1000, - channelDepth: 1000, - electrodeDepth: 1000 - }; - - this.__units = { - componentSpacing: "μm", - rotation: "°", - height: "μm", - inletWidth: "μm", - inletLength: "μm", - electrodeWidth: "μm", - electrodeLength: "μm", - electrodeDistance: "μm", - sensorWidth: "μm", - sensorLength: "μm", - channelDepth: "μm", - electrodeDepth: "μm" - }; - - this.__minimum = { - componentSpacing: 0, - rotation: 0, - height: 10, - inletWidth: 0.5 * 1000, - inletLength: 5 * 1000, - electrodeWidth: 1 * 1000, - electrodeLength: 2 * 1000, - electrodeDistance: 1 * 1000, - sensorWidth: 0.5 * 1000, - sensorLength: 1.5 * 1000, - channelDepth: 1000, - electrodeDepth: 1000 - }; - - this.__maximum = { - componentSpacing: 10000, - rotation: 360, - height: 1200, - inletWidth: 2 * 1000, - inletLength: 15 * 1000, - electrodeWidth: 3 * 1000, - electrodeLength: 6 * 1000, - electrodeDistance: 3 * 1000, - sensorWidth: 1.5 * 1000, - sensorLength: 4.5 * 1000, - channelDepth: 1000, - electrodeDepth: 1000 - }; - - this.__placementTool = "multilayerPositionTool"; - - this.__toolParams = { - cursorPosition: "position" - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - rotation: "rotation", - inletWidth: "inletWidth", - inletLength: "inletLength", - electrodeWidth: "electrodeWidth", - electrodeLength: "electrodeLength", - electrodeDistance: "electrodeDistance", - sensorWidth: "sensorWidth", - sensorLength: "sensorLength", - channelDepth: "channelDepth", - electrodeDepth: "electrodeDepth" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - rotation: "rotation", - inletWidth: "inletWidth", - inletLength: "inletLength", - electrodeWidth: "electrodeWidth", - electrodeLength: "electrodeLength", - electrodeDistance: "electrodeDistance", - sensorWidth: "sensorWidth", - sensorLength: "sensorLength", - channelDepth: "channelDepth", - electrodeDepth: "electrodeDepth" - }; - - this.__renderKeys = ["FLOW", "INTEGRATION"]; - - this.__mint = "DROPLET CAPACITANCE SENSOR"; - - this.__zOffsetKeys = { - FLOW: "height", - INTEGRATION: "electrodeDepth" - }; - - this.__substrateOffset = { - FLOW: "0", - INTEGRATION: "0" - }; - } - - getPorts(params: { [k: string]: any }) { - const inletLength = params.inletLength; - - const ports = []; - - ports.push(new ComponentPort(-inletLength / 2, 0, "1", LogicalLayerType.FLOW)); - - ports.push(new ComponentPort(inletLength / 2, 0, "2", LogicalLayerType.FLOW)); - - return ports; - } - - __renderFlow(params: { [k: string]: any }) { - const rotation = params.rotation; - const x = params.position[0]; - const y = params.position[1]; - const color = params.color; - const inletWidth = params.inletWidth; - const inletLength = params.inletLength; - const serp = new paper.CompoundPath(""); - - // inlet - const topLeft = new paper.Point(x - inletLength / 2, y - inletWidth / 2); - const bottomRight = new paper.Point(x + inletLength / 2, y + inletWidth / 2); - - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - serp.rotate(rotation, new paper.Point(x, y)); - - serp.fillColor = color; - return serp; - } - - __renderIntegrate(params: { [k: string]: any }) { - const rotation = params.rotation; - const x = params.position[0]; - const y = params.position[1]; - const color = params.color; - const inletWidth = params.inletWidth; - const electrodeWidth = params.electrodeWidth; - const electrodeLength = params.electrodeLength; - const electrodeDistance = params.electrodeDistance; - const sensorWidth = params.sensorWidth; - const sensorLength = params.sensorLength; - const serp = new paper.CompoundPath(""); - - // top electrode - let topLeft = new paper.Point(x - electrodeWidth / 2, y - inletWidth / 2 - electrodeDistance - sensorWidth / 2 - electrodeLength); - let bottomRight = new paper.Point(x + electrodeWidth / 2, y - inletWidth / 2 - electrodeDistance - sensorWidth / 2); - - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // top sensor - let elli = new paper.Path.Ellipse({ - point: [x - sensorLength / 2, y - inletWidth / 2 - electrodeDistance - sensorWidth], - size: [sensorLength, sensorWidth] - }); - - serp.addChild(elli); - - // bottom electrode - topLeft = new paper.Point(x - electrodeWidth / 2, y + inletWidth / 2 + electrodeDistance + sensorWidth / 2 + electrodeLength); - bottomRight = new paper.Point(x + electrodeWidth / 2, y + inletWidth / 2 + electrodeDistance + sensorWidth / 2); - - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // bottom sensor - elli = new paper.Path.Ellipse({ - point: [x - sensorLength / 2, y + inletWidth / 2 + electrodeDistance], - size: [sensorLength, sensorWidth] - }); - - serp.addChild(elli); - - serp.rotate(rotation, new paper.Point(x, y)); - - serp.fillColor = color; - return serp; - } - - render2D(params: { [k: string]: any }, key = "FLOW") { - if (key === "FLOW") { - return this.__renderFlow(params); - } else if (key === "INTEGRATION") { - return this.__renderIntegrate(params); - } - throw new Error("Unknown render key found in DROPLET CAPACITANCE SENSOR: " + key); - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - const ret = new paper.CompoundPath(""); - const flow = this.render2D(params, "FLOW"); - const integrate = this.render2D(params, "INTEGRATION"); - ret.addChild(integrate); - ret.addChild(flow); - ret.fillColor = params.color; - ret.fillColor!.alpha = 0.5; - return ret; - } -} diff --git a/src/app/library/cathode.ts b/src/app/library/cathode.ts deleted file mode 100644 index cea15b3d..00000000 --- a/src/app/library/cathode.ts +++ /dev/null @@ -1,127 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class Cahode extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - cathodeRadius: "Float", - pegRadius: "Float", - pegThickness: "Float", - height: "Float", - rotation: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - cathodeRadius: 0.9 * 1000, - pegRadius: 0.7 * 1000, - pegThickness: 0.3 * 1000, - height: 1.1 * 1000, - rotation: 0 - }; - - this.__units = { - componentSpacing: "μm", - cathodeRadius: "μm", - pegRadius: "μm", - pegThickness: "μm", - height: "μm", - rotation: "°" - }; - - this.__minimum = { - componentSpacing: 0, - cathodeRadius: 0.4 * 10, - pegRadius: 0.1 * 1000, - pegThickness: 0.1 * 1000, - height: 10, - rotation: 0 - }; - - this.__maximum = { - componentSpacing: 10000, - cathodeRadius: 2000, - pegRadius: 2 * 1000, - pegThickness: 2 * 1000, - height: 1200, - rotation: 90 - }; - - this.__placementTool = "componentPositionTool"; - - this.__toolParams = { - position: "position" - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - cathodeRadius: "cathodeRadius", - pegRadius: "pegRadius", - pegThickness: "pegThickness", - rotation: "rotation" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - cathodeRadius: "cathodeRadius", - pegRadius: "pegRadius", - pegThickness: "pegThickness", - rotation: "rotation" - }; - - this.__renderKeys = ["FLOW"]; - - this.__mint = "CATHODE"; - } - - render2D(params: { [k: string]: any }, key: string): paper.PathItem { - // Regardless of the key... - const position = params.position; - const radius = params.cathodeRadius; - const pegradius = params.pegRadius; - const pegthickness = params.pegThickness; - const rotation = params.rotation; - const color1 = params.color; - const pos = new paper.Point(position[0], position[1]); - const outerCircle = new paper.Path.Circle(pos, radius); - outerCircle.fillColor = color1; - - const peg1 = new paper.Path.Rectangle(new paper.Rectangle(position[0] - pegradius / 2, position[1] - pegthickness / 2, pegradius, pegthickness)); - const peg2 = new paper.Path.Rectangle(new paper.Rectangle(position[0] - pegthickness / 2, position[1] - pegradius / 2, pegthickness, pegradius)); - const finalCircle = outerCircle.subtract(peg1.unite(peg2)); - finalCircle.fillColor = color1; - outerCircle.remove(); - peg1.remove(); - peg2.remove(); - return (finalCircle.rotate(rotation, pos) as unknown) as paper.PathItem; - } - - render2DTarget(key: string | null, params: { [k: string]: any }): paper.PathItem { - if (key === null) { - key = this.__renderKeys[0]; - } - const render = this.render2D(params, key); - render.fillColor!.alpha = 0.5; - return render; - } - - getPorts(params: { [k: string]: any }) { - const ports = []; - - ports.push(new ComponentPort(0, 0, "1", LogicalLayerType.FLOW)); - - return ports; - } -} diff --git a/src/app/library/celltrapL.ts b/src/app/library/celltrapL.ts deleted file mode 100755 index 4f3c0d8d..00000000 --- a/src/app/library/celltrapL.ts +++ /dev/null @@ -1,218 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class CellTrapL extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - chamberLength: "Float", - feedingChannelWidth: "Float", - rotation: "Float", - chamberWidth: "Float", - numberOfChambers: "Float", - chamberSpacing: "Float", - height: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - chamberLength: 1.2 * 1000, - feedingChannelWidth: 0.41 * 1000, - rotation: 270, - chamberWidth: 1.23 * 1000, - numberOfChambers: 6, - chamberSpacing: 2.46 * 1000, - height: 250 - }; - - this.__units = { - componentSpacing: "μm", - chamberLength: "μm", - feedingChannelWidth: "μm", - rotation: "°", - chamberWidth: "μm", - numberOfChambers: "", - chamberSpacing: "μm", - height: "μm" - }; - - this.__minimum = { - componentSpacing: 0, - chamberLength: 30, - feedingChannelWidth: 10, - chamberWidth: 30, - numberOfChambers: 1, - chamberSpacing: 30, - height: 10, - rotation: 0 - }; - - this.__maximum = { - componentSpacing: 10000, - chamberLength: 6000, - feedingChannelWidth: 2000, - chamberWidth: 6000, - numberOfChambers: 100, - chamberSpacing: 12 * 1000, - height: 1200, - rotation: 360 - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - rotation: "rotation", - chamberWidth: "chamberWidth", - chamberLength: "chamberLength", - numberOfChambers: "numberOfChambers", - chamberSpacing: "chamberSpacing", - feedingChannelWidth: "feedingChannelWidth", - height: "height" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - rotation: "rotation", - chamberWidth: "chamberWidth", - chamberLength: "chamberLength", - numberOfChambers: "numberOfChambers", - chamberSpacing: "chamberSpacing", - feedingChannelWidth: "feedingChannelWidth", - height: "height" - }; - - this.__placementTool = "CellPositionTool"; - - this.__toolParams = { - position: "position" - }; - - this.__renderKeys = ["FLOW", "CELL"]; - - this.__mint = "LONG CELL TRAP"; - - this.__zOffsetKeys = { - FLOW: "height", - CELL: "height" - }; - - this.__substrateOffset = { - FLOW: "0", - CELL: "0" - }; - } - - getPorts(params: { [k: string]: any }) { - const chamberLength = params.chamberLength; - const numChambers = params.numberOfChambers; - const chamberWidth = params.chamberWidth; - const feedingChannelWidth = params.feedingChannelWidth; - const chamberSpacing = params.chamberSpacing; - - const ports = []; - - ports.push(new ComponentPort(0, chamberLength + feedingChannelWidth / 2, "1", LogicalLayerType.FLOW)); - - ports.push(new ComponentPort((numChambers / 2) * (chamberWidth + chamberSpacing) + chamberSpacing, chamberLength + feedingChannelWidth / 2, "2", LogicalLayerType.FLOW)); - - return ports; - } - - render2D(params: { [k: string]: any }, key = "FLOW") { - if (key === "FLOW") { - return this.__drawFlow(params); - } else if (key === "CELL") { - return this.__drawCell(params); - } else { - const flow = this.__drawFlow(params); - const control = this.__drawCell(params); - const ret = new paper.CompoundPath(""); - ret.addChild(flow); - ret.addChild(control); - return ret; - } - - throw new Error("Unknown key: " + key); - - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - const traps = this.__drawFlow(params); - traps.addChild(this.__drawCell(params)); - traps.fillColor!.alpha = 0.5; - return traps; - } - - __drawFlow(params: { [k: string]: any }) { - const rotation = params.rotation; - const position = params.position; - const chamberLength = params.chamberLength; - const numChambers = params.numberOfChambers; - const chamberWidth = params.chamberWidth; - const feedingChannelWidth = params.feedingChannelWidth; - const chamberSpacing = params.chamberSpacing; - - const color = params.color; - const x = position[0]; - const y = position[1]; - const chamberList = new paper.CompoundPath(""); - chamberList.fillColor = color; - let rec; - let traps; - let channels; - - const startPoint = new paper.Point(x, y + chamberLength); - channels = new paper.Path.Rectangle({ - point: startPoint, - size: [(numChambers / 2) * (chamberWidth + chamberSpacing) + chamberSpacing, feedingChannelWidth], - fillColor: color, - strokeWidth: 0 - }); - chamberList.addChild(channels); - - traps = new paper.CompoundPath(chamberList); - traps.fillColor = color; - traps.rotate(rotation, new paper.Point(x, y)); - return traps; - } - - __drawCell(params: { [k: string]: any }) { - const rotation = params.rotation; - const position = params.position; - const chamberLength = params.chamberLength; - const numChambers = params.numberOfChambers; - const chamberWidth = params.chamberWidth; - const feedingChannelWidth = params.feedingChannelWidth; - const chamberSpacing = params.chamberSpacing; - const color = params.color; - const x = position[0]; - const y = position[1]; - const chamberList = new paper.CompoundPath(""); - let rec; - - for (let i = 0; i < numChambers / 2; i++) { - const startPoint = new paper.Point(x + i * (chamberWidth + chamberSpacing) + chamberSpacing, y); - rec = new paper.Path.Rectangle({ - size: [chamberWidth, 2 * chamberLength + feedingChannelWidth], - point: startPoint, - fillColor: color, - strokeWidth: 0 - }); - chamberList.addChild(rec); - } - - chamberList.fillColor = color; - chamberList.rotate(rotation, new paper.Point(x, y)); - return chamberList; - } -} diff --git a/src/app/library/celltrapS.ts b/src/app/library/celltrapS.ts deleted file mode 100644 index 8ed110d7..00000000 --- a/src/app/library/celltrapS.ts +++ /dev/null @@ -1,202 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class CellTrapS extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - rotation: "Float", - height: "Float", - channelWidth: "Float", - channelLength: "Float", - chamberWidth: "Float", - chamberLength: "Float", - chamberHeight: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - rotation: 0, - height: 250, - channelWidth: 1 * 1000, - channelLength: 4 * 1000, - chamberWidth: 2.5 * 1000, - chamberLength: 2.5 * 1000, - chamberHeight: 250 - }; - - this.__units = { - componentSpacing: "μm", - rotation: "°", - height: "μm", - channelWidth: "μm", - channelLength: "μm", - chamberWidth: "μm", - chamberLength: "μm", - chamberHeight: "μm" - }; - - this.__minimum = { - componentSpacing: 0, - rotation: 0, - height: 10, - channelWidth: 0.5 * 1000, - channelLength: 2.5 * 1000, - chamberWidth: 1.5 * 1000, - chamberLength: 1.5 * 1000, - chamberHeight: 10 - }; - - this.__maximum = { - componentSpacing: 10000, - rotation: 360, - height: 1200, - channelWidth: 2 * 1000, - channelLength: 6 * 1000, - chamberWidth: 4 * 1000, - chamberLength: 4 * 1000, - chamberHeight: 1200 - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - rotation: "rotation", - height: "height", - channelWidth: "channelWidth", - channelLength: "channelLength", - chamberWidth: "chamberWidth", - chamberLength: "chamberLength", - chamberHeight: "chamberHeight" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - rotation: "rotation", - height: "height", - channelWidth: "channelWidth", - channelLength: "channelLength", - chamberWidth: "chamberWidth", - chamberLength: "chamberLength", - chamberHeight: "chamberHeight" - }; - - this.__placementTool = "CellPositionTool"; - - this.__toolParams = { - position: "position" - }; - - this.__renderKeys = ["FLOW", "CELL"]; - - this.__mint = "SQUARE CELL TRAP"; - - this.__zOffsetKeys = { - FLOW: "height", - CELL: "chamberHeight" - }; - - this.__substrateOffset = { - FLOW: "0", - CELL: "0" - }; - } - - getPorts(params: { [k: string]: any }) { - const channelLength = params.channelLength; - - const ports = []; - - ports.push(new ComponentPort(-channelLength / 2, 0, "1", LogicalLayerType.FLOW)); - - ports.push(new ComponentPort(channelLength / 2, 0, "2", LogicalLayerType.FLOW)); - - ports.push(new ComponentPort(0, -channelLength / 2, "3", LogicalLayerType.FLOW)); - - ports.push(new ComponentPort(0, channelLength / 2, "4", LogicalLayerType.FLOW)); - - return ports; - } - - render2D(params: { [k: string]: any }, key: string) { - if (key === "FLOW") { - return this.__drawFlow(params); - } else if (key === "CELL") { - return this.__drawCell(params); - }else{ - throw new Error("Unknown key for celltrapS: " + key); - } - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - const traps = this.__drawFlow(params); - traps.addChild(this.__drawCell(params)); - - traps.fillColor!.alpha = 0.5; - - return traps; - } - - __drawFlow(params: { [k: string]: any }) { - const rotation = params.rotation; - const position = params.position; - const color = params.color; - const x = position[0]; - const y = position[1]; - const channelWidth = params.channelWidth; - const channelLength = params.channelLength; - - const traps = new paper.CompoundPath(""); - - // horizontal channel - let topLeft = new paper.Point(x - channelLength / 2, y - channelWidth / 2); - let bottomRight = new paper.Point(x + channelLength / 2, y + channelWidth / 2); - - traps.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // vertical channel - topLeft = new paper.Point(x - channelWidth / 2, y - channelLength / 2); - bottomRight = new paper.Point(x + channelWidth / 2, y + channelLength / 2); - - traps.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - traps.fillColor = color; - - traps.rotate(rotation, new paper.Point(x, y)); - - return traps; - } - - __drawCell(params: { [k: string]: any }) { - const rotation = params.rotation; - const color = params.color; - const position = params.position; - const x = position[0]; - const y = position[1]; - const chamberWidth = params.chamberWidth; - const chamberLength = params.chamberLength; - - const chamberList = new paper.CompoundPath(""); - - // chamber - const topLeft = new paper.Point(x - chamberWidth / 2, y - chamberLength / 2); - const bottomRight = new paper.Point(x + chamberWidth / 2, y + chamberLength / 2); - - chamberList.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - chamberList.fillColor = color; - chamberList.rotate(rotation, new paper.Point(x, y)); - - return chamberList; - } -} diff --git a/src/app/library/chamber.ts b/src/app/library/chamber.ts deleted file mode 100755 index 7eade239..00000000 --- a/src/app/library/chamber.ts +++ /dev/null @@ -1,150 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class Chamber extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - width: "Float", - length: "Float", - height: "Float", - cornerRadius: "Float", - rotation: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - width: 5000, - length: 5000, - height: 250, - cornerRadius: 200, - rotation: 0 - }; - - this.__units = { - componentSpacing: "μm", - width: "μm", - length: "μm", - height: "μm", - cornerRadius: "μm", - rotation: "°" - }; - - this.__minimum = { - componentSpacing: 0, - width: 5, - length: 5, - height: 1, - cornerRadius: 1, - rotation: 0 - }; - - this.__maximum = { - componentSpacing: 10000, - width: 50000, - length: 50000, - height: 50000, - cornerRadius: 1000, - rotation: 360 - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - width: "width", - length: "length", - height: "height", - cornerRadius: "cornerRadius", - rotation: "rotation" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - position: "position", - width: "width", - length: "length", - height: "height", - cornerRadius: "cornerRadius", - rotation: "rotation" - }; - - this.__placementTool = "componentPositionTool"; - - this.__toolParams = { - position: "position" - }; - - this.__renderKeys = ["FLOW"]; - - this.__mint = "REACTION CHAMBER"; - - this.__zOffsetKeys = { - FLOW: "height" - }; - - this.__substrateOffset = { - FLOW: "0" - }; - } - - getPorts(params: { [k: string]: any }) { - const l = params.length; - const w = params.width; - - const ports = []; - - ports.push(new ComponentPort(0, -l / 2, "1", LogicalLayerType.FLOW)); - - ports.push(new ComponentPort(w / 2, 0, "2", LogicalLayerType.FLOW)); - - ports.push(new ComponentPort(0, l / 2, "3", LogicalLayerType.FLOW)); - - ports.push(new ComponentPort(-w / 2, 0, "4", LogicalLayerType.FLOW)); - - return ports; - } - - render2D(params: { [k: string]: any }, key: string) { - const position = params.position; - const px = position[0]; - const py = position[1]; - const l = params.length; - const w = params.width; - const rotation = params.rotation; - const color = params.color; - const radius = params.cornerRadius; - - const rendered = new paper.CompoundPath(""); - - const rec = new paper.Path.Rectangle({ - point: new paper.Point(px - w / 2, py - l / 2), - size: [w, l], - radius: radius - }); - - rendered.addChild(rec); - - rendered.fillColor = color; - rendered.rotate(rotation, new paper.Point(px, py)); - return rendered; - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - if (key === null) { - key = this.__renderKeys[0]; - } - const render = this.render2D(params, key); - render.fillColor!.alpha = 0.5; - return render; - } -} diff --git a/src/app/library/channel.ts b/src/app/library/channel.ts deleted file mode 100644 index 4d6686e7..00000000 --- a/src/app/library/channel.ts +++ /dev/null @@ -1,105 +0,0 @@ -import Template from "./template"; -import paper from "paper"; - -export default class Channel extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - start: "Point", - end: "Point" - }; - - this.__defaults = { - channelWidth: 0.8 * 1000, - height: 250 - }; - - this.__heritable = { - channelWidth: "Float", - height: "Float" - }; - - this.__units = { - channelWidth: "μm", - height: "μm" - }; - - this.__minimum = { - channelWidth: 3, - height: 10 - }; - - this.__maximum = { - channelWidth: 12000, - height: 1200 - }; - - this.__placementTool = "DragTool"; - - this.__toolParams = { - start: "start", - end: "end" - }; - - this.__featureParams = { - start: "start", - end: "end", - width: "channelWidth" - }; - - this.__targetParams = { - diameter: "channelWidth", - channelWidth: "channelWidth" - }; - - this.__renderKeys = ["FLOW"]; - - this.__mint = "CHANNEL"; - - this.__zOffsetKeys = { - FLOW: "height" - }; - - this.__substrateOffset = { - FLOW: "0" - }; - } - - render2D(params: { [k: string]: any }, key: string) { - // Regardless of the key... - const start = params.start; - const end = params.end; - const color = params.color; - const width = params.width; - const baseColor = params.baseColor; - const startPoint = new paper.Point(start[0], start[1]); - const endPoint = new paper.Point(end[0], end[1]); - const vec = endPoint.subtract(startPoint); - const rec = new paper.Path.Rectangle({ - size: [vec.length, width], - point: start, - // radius: width/2, - fillColor: color, - strokeWidth: 0 - }); - rec.translate(new paper.Point(0, -width / 2)); - rec.rotate(vec.angle, start); - return rec; - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - const thickness = params.channelWidth / 5; - const length = params.channelWidth; - const x = params.position[0]; - const y = params.position[1]; - const color = params.color; - let chair = new paper.Path.Rectangle(new paper.Rectangle(x - length / 2, y - thickness / 2, length, thickness)); - let chairtarget = chair.unite(new paper.Path.Rectangle(new paper.Rectangle(x - thickness / 2, y - length / 2, thickness, length))); - chairtarget.fillColor = color; - chairtarget.fillColor!.alpha = 0.5; - return chair; - } -} diff --git a/src/app/library/chemostatring.ts b/src/app/library/chemostatring.ts deleted file mode 100644 index f0ce9d38..00000000 --- a/src/app/library/chemostatring.ts +++ /dev/null @@ -1,1170 +0,0 @@ -import Template from "./template"; -import paper, { CompoundPath } from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class ChemostatRing extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - flowChannelWidth: "Float", - controlChannelWidth: "Float", - chemostatChannelWidth: "Float", - radius: "Float", - rotation: "Float", - volume: "Float", - height: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - flowChannelWidth: 100, - controlChannelWidth: 50, - chemostatChannelWidth: 100, - radius: 400, - rotation: 0, - volume: 30000000, - height: 20 - }; - - this.__units = { - bendSpacing: "μm", - numberOfBends: "", - channelWidth: "μm", - bendLength: "μm", - componentSpacing: "μm", - flowChannelWidth: "μm", - controlChannelWidth: "μm", - chemostatChannelWidth: "μm", - radius: "μm", - rotation: "°", - volume: "μm3", - height: "μm" - }; - - this.__minimum = { - componentSpacing: 0, - flowChannelWidth: 0.1 * 1000, - controlChannelWidth: 0.1 * 1000, - chemostatChannelWidth: 0.2 * 1000, - radius: 0.2 * 1000, - rotation: 0, - volume: 0.1 * 1000 * 1 * 1000 * 4 * 0.2 * 1000, - height: 0.2 * 1000 - }; - - this.__maximum = { - componentSpacing: 10000, - flowChannelWidth: 0.3 * 10000, - controlChannelWidth: 0.15 * 10000, - chemostatChannelWidth: 0.5 * 10000, - radius: 10000, - rotation: 260, - volume: 0.5 * 10000 * 10 * 1000 * 4 * 1 * 10000, - height: 1 * 10000 - }; - - this.__placementTool = "multilayerPositionTool"; - - this.__toolParams = { - cursorPosition: "position" - }; - - this.__featureParams = { - position: "position", - componentSpacing: "componentSpacing", - flowChannelWidth: "flowChannelWidth", - controlChannelWidth: "controlChannelWidth", - chemostatChannelWidth: "chemostatChannelWidth", - radius: "radius", - rotation: "rotation", - volume: "volume", - height: "height" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - flowChannelWidth: "flowChannelWidth", - controlChannelWidth: "controlChannelWidth", - chemostatChannelWidth: "chemostatChannelWidth", - radius: "radius", - rotation: "rotation", - volume: "volume", - height: "height" - }; - - this.__renderKeys = ["FLOW", "CONTROL"]; - - this.__mint = "CHEMOSTAT RING"; - - this.__zOffsetKeys = { - FLOW: "height", - CONTROL: "height" - }; - - this.__substrateOffset = { - FLOW: "0", - CONTROL: "+1" - }; - } - - getPorts(params: { [k: string]: any }) { - const flowChannelWidth = params.flowChannelWidth; - const controlChannelWidth = params.controlChannelWidth; - const chemostatChannelWidth = params.chemostatChannelWidth; - const volume = params.volume; - const height = params.height; - const radius = params.radius; - - const area = volume / height; - const chemostatLength = area / (4 * chemostatChannelWidth); - - const controlSpacing = chemostatLength / 10; - const controlendpoint = (-7 * chemostatLength) / 8; - const bendDist = chemostatLength / 15; - - const ports = []; - - // flow - ports.push(new ComponentPort(-chemostatLength / 3 - chemostatLength / 2, -chemostatLength / 3, "1", LogicalLayerType.FLOW)); - ports.push(new ComponentPort(-chemostatLength / 3 - chemostatLength / 5, -chemostatLength / 3 - chemostatLength / 3, "2", LogicalLayerType.FLOW)); - ports.push(new ComponentPort(-chemostatLength / 3 + chemostatLength / 5, -chemostatLength / 3 - chemostatLength / 3, "3", LogicalLayerType.FLOW)); - ports.push(new ComponentPort(-chemostatLength / 3 + chemostatLength / 2, -chemostatLength / 3, "4", LogicalLayerType.FLOW)); - // ports.push(new ComponentPort(chemostatChannelWidth + chemostatLength + 2 * chemostatLength/5, chemostatChannelWidth/2 + 7 * chemostatLength/11, "5", "FLOW")); - - // control - // 1 - ports.push(new ComponentPort(-chemostatLength / 3 - chemostatLength / 5 - controlSpacing - radius, controlendpoint, "5", LogicalLayerType.CONTROL)); - // 2 - ports.push(new ComponentPort(-chemostatLength / 3 - chemostatLength / 5 + 1.3 * radius, controlendpoint, "6", LogicalLayerType.CONTROL)); - // 3 - ports.push(new ComponentPort(-chemostatLength / 3 - chemostatLength / 5 + 1.7 * radius, controlendpoint, "7", LogicalLayerType.CONTROL)); - // 4 - ports.push(new ComponentPort(-chemostatLength / 3 + chemostatLength / 5 - controlSpacing - radius, controlendpoint, "8", LogicalLayerType.CONTROL)); - // 5 - ports.push(new ComponentPort(-chemostatLength / 3 + chemostatLength / 5 + 1.3 * radius, controlendpoint, "9", LogicalLayerType.CONTROL)); - // 6 - ports.push(new ComponentPort(-chemostatLength / 3 + chemostatLength / 5 + 1.7 * radius, controlendpoint, "10", LogicalLayerType.CONTROL)); - - let originx = chemostatChannelWidth / 2 + (3 * chemostatLength) / 7; - let originy = chemostatChannelWidth / 2; - - // 7 - ports.push(new ComponentPort(originx - controlSpacing - 0.5 * radius, controlendpoint, "11", LogicalLayerType.CONTROL)); - // 8 - ports.push(new ComponentPort(originx + 1.3 * radius, controlendpoint, "12", LogicalLayerType.CONTROL)); - // 9 - ports.push(new ComponentPort(originx + 1.7 * radius, controlendpoint, "13", LogicalLayerType.CONTROL)); - - originx = (5 * chemostatLength) / 6; - originy = chemostatChannelWidth / 2; - - // 10 - ports.push(new ComponentPort(originx - controlSpacing - 0.5 * radius, controlendpoint, "14", LogicalLayerType.CONTROL)); - // 11 - ports.push(new ComponentPort(originx + 1.3 * radius, controlendpoint, "15", LogicalLayerType.CONTROL)); - // 12 - ports.push(new ComponentPort(originx + 1.7 * radius, controlendpoint, "16", LogicalLayerType.CONTROL)); - - originx = chemostatChannelWidth / 2; - originy = chemostatLength / 5; - - // 13 - ports.push(new ComponentPort(controlendpoint, originy - controlSpacing - 0.5 * radius, "17", LogicalLayerType.CONTROL)); - // 14 - ports.push(new ComponentPort(controlendpoint, originy + 1.3 * radius, "18", LogicalLayerType.CONTROL)); - // 15 - ports.push(new ComponentPort(controlendpoint, originy + 1.7 * radius, "19", LogicalLayerType.CONTROL)); - - originx = chemostatChannelWidth / 2; - originy = chemostatLength / 5 + chemostatLength / 2; - - // 16 - ports.push(new ComponentPort(controlendpoint, originy - controlSpacing - 0.5 * radius, "20", LogicalLayerType.CONTROL)); - // 17 - ports.push(new ComponentPort(controlendpoint, originy + 1.3 * radius, "21", LogicalLayerType.CONTROL)); - // 18 - ports.push(new ComponentPort(controlendpoint, originy + 1.7 * radius, "22", LogicalLayerType.CONTROL)); - - originx = chemostatChannelWidth / 2 + chemostatLength; - originy = chemostatChannelWidth / 2 + (2 * chemostatLength) / 5; - - // 19 - ports.push(new ComponentPort(2 * chemostatLength, originy - controlSpacing - 0.5 * radius, "23", LogicalLayerType.CONTROL)); - // 20 - ports.push(new ComponentPort(2 * chemostatLength, originy + 1.3 * radius, "24", LogicalLayerType.CONTROL)); - // 21 - ports.push(new ComponentPort(2 * chemostatLength, originy + 1.7 * radius, "25", LogicalLayerType.CONTROL)); - - originx = chemostatChannelWidth / 2 + chemostatLength; - originy = chemostatChannelWidth / 2 + (4 * chemostatLength) / 5; - - // 22 - ports.push(new ComponentPort(2 * chemostatLength, originy - controlSpacing - 0.5 * radius, "26", LogicalLayerType.CONTROL)); - // 23 - ports.push(new ComponentPort(2 * chemostatLength, originy + 1.3 * radius, "27", LogicalLayerType.CONTROL)); - // 24 - ports.push(new ComponentPort(2 * chemostatLength, originy + 1.7 * radius, "28", LogicalLayerType.CONTROL)); - - originx = chemostatChannelWidth / 2 + chemostatLength / 4; - originy = chemostatLength + chemostatChannelWidth / 2; - - // 25 - ports.push(new ComponentPort(originx - 0.3 * controlSpacing, 2 * chemostatLength, "29", LogicalLayerType.CONTROL)); - // 26 - ports.push(new ComponentPort(originx + 0.5 * controlSpacing, 2 * chemostatLength, "30", LogicalLayerType.CONTROL)); - // 27 - ports.push(new ComponentPort(originx + 0.4 * controlSpacing + 0.3 * controlSpacing, 2 * chemostatLength, "31", LogicalLayerType.CONTROL)); - - originx = chemostatChannelWidth / 2 + (3 * chemostatLength) / 7; - originy = chemostatLength + chemostatChannelWidth / 2; - - // 28 - ports.push(new ComponentPort(originx - 0.3 * controlSpacing, 2 * chemostatLength, "32", LogicalLayerType.CONTROL)); - // 29 - ports.push(new ComponentPort(originx - 0.5 * controlSpacing, 2 * chemostatLength, "33", LogicalLayerType.CONTROL)); - // 30 - ports.push(new ComponentPort(originx + 0.3 * controlSpacing, 2 * chemostatLength, "34", LogicalLayerType.CONTROL)); - - // 31 - ports.push(new ComponentPort(originx + 0.55 * controlSpacing, 2 * chemostatLength, "35", LogicalLayerType.CONTROL)); - // 32 - ports.push(new ComponentPort(originx + 0.85 * controlSpacing, 2 * chemostatLength, "36", LogicalLayerType.CONTROL)); - // 33 - ports.push(new ComponentPort(originx + 1.15 * controlSpacing, 2 * chemostatLength, "37", LogicalLayerType.CONTROL)); - - originx = chemostatChannelWidth / 2 + (3 * chemostatLength) / 5; - originy = chemostatLength + chemostatChannelWidth / 2; - - // 34 - ports.push(new ComponentPort(originx - 0.3 * controlSpacing, 2 * chemostatLength, "38", LogicalLayerType.CONTROL)); - // 35 - ports.push(new ComponentPort(originx + 0.5 * controlSpacing, 2 * chemostatLength, "49", LogicalLayerType.CONTROL)); - // 36 - ports.push(new ComponentPort(originx + 0.4 * controlSpacing + 0.3 * controlSpacing, 2 * chemostatLength, "40", LogicalLayerType.CONTROL)); - return ports; - } - - render2D(params: { [k: string]: any }, key: string) { - if (key === "FLOW") { - return this.__drawFlow(params); - } else if (key === "CONTROL") { - return this.__drawControl(params); - } - else{ - throw new Error("Unknown key for computing chemostat ring: " + key); - } - } - - __drawFlow(params: { [k: string]: any }) { - const x = params.position[0]; - const y = params.position[1]; - const flowChannelWidth = params.flowChannelWidth; - const controlChannelWidth = params.controlChannelWidth; - const chemostatChannelWidth = params.chemostatChannelWidth; - const volume = params.volume; - const height = params.height; - const radius = params.radius; - const rotation = params.rotation; - const color = params.color; - const serp = new paper.CompoundPath(""); - - const area = volume / height; - const chemostatLength = area / (4 * chemostatChannelWidth); - - /// / chemostat ring - - // chemostat ring top - let topLeft = new paper.Point(x + chemostatChannelWidth, y); - let bottomRight = new paper.Point(x + chemostatChannelWidth + chemostatLength, y + chemostatChannelWidth); - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // chemostat ring right - topLeft = new paper.Point(x + chemostatLength, y + chemostatChannelWidth); - bottomRight = new paper.Point(x + chemostatChannelWidth + chemostatLength, y + chemostatChannelWidth + chemostatLength); - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // chemostat ring bottom - topLeft = new paper.Point(x, y + chemostatLength); - bottomRight = new paper.Point(x + chemostatLength, y + chemostatLength + chemostatChannelWidth); - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // chemostat ring left - topLeft = new paper.Point(x, y); - bottomRight = new paper.Point(x + chemostatChannelWidth, y + chemostatLength); - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // in top left vert - topLeft = new paper.Point(x + chemostatChannelWidth / 2 + chemostatLength / 4 - flowChannelWidth / 2, y + chemostatChannelWidth / 2); - bottomRight = new paper.Point(x + chemostatChannelWidth / 2 + chemostatLength / 4 + flowChannelWidth / 2, y + chemostatChannelWidth / 2 + (2 * chemostatLength) / 5); - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // in top right vert - topLeft = new paper.Point(x + chemostatChannelWidth / 2 + (3 * chemostatLength) / 5 - flowChannelWidth / 2, y + chemostatChannelWidth / 2); - bottomRight = new paper.Point(x + chemostatChannelWidth / 2 + (3 * chemostatLength) / 5 + flowChannelWidth / 2, y + chemostatChannelWidth / 2 + (2 * chemostatLength) / 5); - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // in top right hori - topLeft = new paper.Point(x + chemostatChannelWidth / 2 + (3 * chemostatLength) / 5, y + chemostatChannelWidth / 2 + chemostatLength / 5 - flowChannelWidth / 2); - bottomRight = new paper.Point(x + chemostatChannelWidth / 2 + chemostatLength, y + chemostatChannelWidth / 2 + chemostatLength / 5 + flowChannelWidth / 2); - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // in top bottom hori - topLeft = new paper.Point(x + chemostatChannelWidth / 2, y + chemostatChannelWidth / 2 + (2 * chemostatLength) / 5 - flowChannelWidth / 2); - bottomRight = new paper.Point(x + chemostatChannelWidth / 2 + (3 * chemostatLength) / 5, y + chemostatChannelWidth / 2 + (2 * chemostatLength) / 5 + flowChannelWidth / 2); - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // in middle left hori - topLeft = new paper.Point(x + chemostatChannelWidth / 2, y + chemostatChannelWidth / 2 + (4 * chemostatLength) / 5 - flowChannelWidth / 2); - bottomRight = new paper.Point(x + chemostatChannelWidth / 2 + chemostatLength / 4, y + chemostatChannelWidth / 2 + (4 * chemostatLength) / 5 + flowChannelWidth / 2); - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // in middle middle vert - topLeft = new paper.Point(x + chemostatChannelWidth / 2 + chemostatLength / 4 - flowChannelWidth / 2, y + chemostatChannelWidth / 2 + chemostatLength / 2); - bottomRight = new paper.Point( - x + chemostatChannelWidth / 2 + chemostatLength / 4 + flowChannelWidth / 2, - y + chemostatChannelWidth / 2 + (4 * chemostatLength) / 5 + flowChannelWidth / 2 - ); - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // in middle middle hori - topLeft = new paper.Point( - x + chemostatChannelWidth / 2 + chemostatLength / 4 - flowChannelWidth / 2, - y + chemostatChannelWidth / 2 + chemostatLength / 2 - flowChannelWidth / 2 - ); - bottomRight = new paper.Point(x + chemostatChannelWidth / 2 + (5 * chemostatLength) / 7, y + chemostatChannelWidth / 2 + chemostatLength / 2 + flowChannelWidth / 2); - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // in top circle - let center = new paper.Point(x + chemostatChannelWidth / 2 + (5 * chemostatLength) / 7, y + chemostatChannelWidth / 2 + chemostatLength / 2); - const circ = new paper.Path.Circle(center, radius); - serp.addChild(circ); - - // calc H - const xval = Math.abs((5 * chemostatLength) / 7 - (3 * chemostatLength) / 5); - const yval = Math.abs(chemostatChannelWidth / 2 + chemostatLength / 2 - (chemostatChannelWidth / 2 + (2 * chemostatLength) / 5)); - const hval = Math.sqrt(Math.pow(xval, 2) + Math.pow(yval, 2)); - const angt = (Math.asin(yval / hval) * 180) / Math.PI; - - // in tilt - topLeft = new paper.Point( - x + chemostatChannelWidth / 2 + (3 * chemostatLength) / 5 - flowChannelWidth / 2, - y + chemostatChannelWidth / 2 + (2 * chemostatLength) / 5 - flowChannelWidth / 2 - ); - bottomRight = new paper.Point( - x + chemostatChannelWidth / 2 + (3 * chemostatLength) / 5 - flowChannelWidth / 2 + hval, - y + chemostatChannelWidth / 2 + (2 * chemostatLength) / 5 + flowChannelWidth / 2 - ); - serp.addChild( - (new paper.Path.Rectangle(topLeft, bottomRight).rotate( - angt, - new paper.Point(x + chemostatChannelWidth / 2 + (3 * chemostatLength) / 5, y + chemostatChannelWidth / 2 + (2 * chemostatLength) / 5) - ) as unknown) as paper.Path.Rectangle - ); - - // in circle bottom vert - topLeft = new paper.Point(x + chemostatChannelWidth / 2 + (5 * chemostatLength) / 7 - flowChannelWidth / 2, y + chemostatChannelWidth / 2 + chemostatLength / 2); - bottomRight = new paper.Point(x + chemostatChannelWidth / 2 + (5 * chemostatLength) / 7 + flowChannelWidth / 2, y + chemostatChannelWidth / 2 + (7 * chemostatLength) / 11); - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // in circle bottom hori - topLeft = new paper.Point( - x + chemostatChannelWidth / 2 + (5 * chemostatLength) / 7 - flowChannelWidth / 2, - y + chemostatChannelWidth / 2 + (7 * chemostatLength) / 11 - flowChannelWidth / 2 - ); - bottomRight = new paper.Point(x + chemostatLength, y + chemostatChannelWidth / 2 + (7 * chemostatLength) / 11 + flowChannelWidth / 2); - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // in bottom right vert - topLeft = new paper.Point(x + (5 * chemostatLength) / 6 - flowChannelWidth / 2, y + chemostatChannelWidth / 2 + (7 * chemostatLength) / 11); - bottomRight = new paper.Point(x + (5 * chemostatLength) / 6 + flowChannelWidth / 2, y + chemostatChannelWidth / 2 + chemostatLength); - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // in bottom middle vert - topLeft = new paper.Point(x + chemostatChannelWidth / 2 + (3 * chemostatLength) / 7 - flowChannelWidth / 2, y + chemostatChannelWidth / 2 + (4 * chemostatLength) / 6); - bottomRight = new paper.Point(x + chemostatChannelWidth / 2 + (3 * chemostatLength) / 7 + flowChannelWidth / 2, y + chemostatChannelWidth / 2 + chemostatLength); - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // in bottom circle - center = new paper.Point(x + chemostatChannelWidth / 2 + (3 * chemostatLength) / 7, y + chemostatChannelWidth / 2 + (4 * chemostatLength) / 6); - serp.addChild(new paper.Path.Circle(center, radius)); - - /// / stuff outside the ring - - // left top hori - topLeft = new paper.Point(x - chemostatLength / 3, y + chemostatLength / 5 - flowChannelWidth / 2); - bottomRight = new paper.Point(x, y + chemostatLength / 5 + flowChannelWidth / 2); - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // left top vert - topLeft = new paper.Point(x - chemostatLength / 3 - flowChannelWidth / 2, y - chemostatLength / 3); - bottomRight = new paper.Point(x - chemostatLength / 3 + flowChannelWidth / 2, y + chemostatLength / 5 + flowChannelWidth / 2); - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // left flow port hori bar - topLeft = new paper.Point(x - chemostatLength / 3 - chemostatLength / 2, y - chemostatLength / 3 - flowChannelWidth / 2); - bottomRight = new paper.Point(x - chemostatLength / 3 + chemostatLength / 2, y - chemostatLength / 3 + flowChannelWidth / 2); - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // horizontal circles - // left - // center = new paper.Point(x - chemostatLength/3 - chemostatLength/2, y - chemostatLength/3); - // serp.addChild(new paper.Path.Circle(center, radius)); - // right - // center = new paper.Point(x - chemostatLength/3 + chemostatLength/2, y - chemostatLength/3); - // serp.addChild(new paper.Path.Circle(center, radius)); - - // left flow port vert - topLeft = new paper.Point(x - chemostatLength / 3 - chemostatLength / 5 - flowChannelWidth / 2, y - chemostatLength / 3 - chemostatLength / 3); - bottomRight = new paper.Point(x - chemostatLength / 3 - chemostatLength / 5 + flowChannelWidth / 2, y - chemostatLength / 3); - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // right flow port vert - topLeft = new paper.Point(x - chemostatLength / 3 + chemostatLength / 5 - flowChannelWidth / 2, y - chemostatLength / 3 - chemostatLength / 3); - bottomRight = new paper.Point(x - chemostatLength / 3 + chemostatLength / 5 + flowChannelWidth / 2, y - chemostatLength / 3); - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // top circles - // left - // center = new paper.Point(x - chemostatLength/3 - chemostatLength/5, y - chemostatLength/3 - chemostatLength/3); - // serp.addChild(new paper.Path.Circle(center, radius)); - - // right - // center = new paper.Point(x - chemostatLength/3 + chemostatLength/5, y - chemostatLength/3 - chemostatLength/3); - // serp.addChild(new paper.Path.Circle(center, radius)); - - // left vert line that goes to bottom - topLeft = new paper.Point(x - chemostatLength / 5 - flowChannelWidth / 2, y + chemostatLength / 5); - bottomRight = new paper.Point(x - chemostatLength / 5 + flowChannelWidth / 2, y + chemostatLength + chemostatChannelWidth + chemostatLength / 5); - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // left middle hori - topLeft = new paper.Point(x - chemostatLength / 5, y + chemostatLength / 5 + chemostatLength / 2 - flowChannelWidth / 2); - bottomRight = new paper.Point(x, y + chemostatLength / 5 + chemostatLength / 2 + flowChannelWidth / 2); - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // bottom hori - topLeft = new paper.Point(x - chemostatLength / 5 - flowChannelWidth / 2, y + chemostatLength + chemostatChannelWidth + chemostatLength / 5 - flowChannelWidth / 2); - bottomRight = new paper.Point( - x + chemostatChannelWidth / 2 + (3 * chemostatLength) / 5, - y + chemostatLength + chemostatChannelWidth + chemostatLength / 5 + flowChannelWidth / 2 - ); - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // bottom left vert - topLeft = new paper.Point(x + chemostatChannelWidth / 2 + chemostatLength / 4 - flowChannelWidth / 2, y + chemostatLength + chemostatChannelWidth / 2); - bottomRight = new paper.Point( - x + chemostatChannelWidth / 2 + chemostatLength / 4 + flowChannelWidth / 2, - y + chemostatLength + chemostatChannelWidth + chemostatLength / 5 - ); - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // bottom middle vert - topLeft = new paper.Point(x + chemostatChannelWidth / 2 + (3 * chemostatLength) / 5 - flowChannelWidth / 2, y + chemostatLength + chemostatChannelWidth / 2); - bottomRight = new paper.Point( - x + chemostatChannelWidth / 2 + (3 * chemostatLength) / 5 + flowChannelWidth / 2, - y + chemostatLength + chemostatChannelWidth + (2 * chemostatLength) / 5 - ); - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // bottom right hori - topLeft = new paper.Point( - x + chemostatChannelWidth / 2 + (3 * chemostatLength) / 5 - flowChannelWidth / 2, - y + chemostatLength + chemostatChannelWidth + (2 * chemostatLength) / 5 - flowChannelWidth / 2 - ); - bottomRight = new paper.Point( - x + chemostatChannelWidth + chemostatLength + (2 * chemostatLength) / 5, - y + chemostatLength + chemostatChannelWidth + (2 * chemostatLength) / 5 + flowChannelWidth / 2 - ); - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // right bottom vert - topLeft = new paper.Point( - x + chemostatChannelWidth + chemostatLength + (2 * chemostatLength) / 5 - flowChannelWidth / 2, - y + chemostatChannelWidth / 2 + (7 * chemostatLength) / 11 - ); - bottomRight = new paper.Point( - x + chemostatChannelWidth + chemostatLength + (2 * chemostatLength) / 5 + flowChannelWidth / 2, - y + chemostatLength + chemostatChannelWidth + (2 * chemostatLength) / 5 + flowChannelWidth / 2 - ); - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - center = new paper.Point(x + chemostatChannelWidth + chemostatLength + (2 * chemostatLength) / 5, y + chemostatChannelWidth / 2 + (7 * chemostatLength) / 11 - radius); - serp.addChild(new paper.Path.Circle(center, radius)); - - // right bottom hori - topLeft = new paper.Point( - x + chemostatChannelWidth + chemostatLength + chemostatLength / 5, - y + chemostatLength + chemostatChannelWidth + chemostatLength / 5 - flowChannelWidth / 2 - ); - bottomRight = new paper.Point( - x + chemostatChannelWidth + chemostatLength + (2 * chemostatLength) / 5, - y + chemostatLength + chemostatChannelWidth + chemostatLength / 5 + flowChannelWidth / 2 - ); - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // right vert that goes to top - topLeft = new paper.Point(x + chemostatChannelWidth + chemostatLength + chemostatLength / 5 - flowChannelWidth / 2, y - chemostatLength / 5); - bottomRight = new paper.Point( - x + chemostatChannelWidth + chemostatLength + chemostatLength / 5 + flowChannelWidth / 2, - y + chemostatLength + chemostatChannelWidth + chemostatLength / 5 + flowChannelWidth / 2 - ); - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // right middle hori - topLeft = new paper.Point(x + chemostatChannelWidth / 2 + chemostatLength, y + chemostatChannelWidth / 2 + (4 * chemostatLength) / 5 - flowChannelWidth / 2); - bottomRight = new paper.Point( - x + chemostatChannelWidth + chemostatLength + chemostatLength / 5, - y + chemostatChannelWidth / 2 + (4 * chemostatLength) / 5 + flowChannelWidth / 2 - ); - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // right top hori - topLeft = new paper.Point(x + chemostatChannelWidth / 2 + chemostatLength, y + chemostatChannelWidth / 2 + (2 * chemostatLength) / 5 - flowChannelWidth / 2); - bottomRight = new paper.Point( - x + chemostatChannelWidth + chemostatLength + chemostatLength / 5, - y + chemostatChannelWidth / 2 + (2 * chemostatLength) / 5 + flowChannelWidth / 2 - ); - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // top hori - topLeft = new paper.Point(x + chemostatChannelWidth / 2 + (3 * chemostatLength) / 7, y - chemostatLength / 5 - flowChannelWidth / 2); - bottomRight = new paper.Point(x + chemostatChannelWidth + chemostatLength + chemostatLength / 5 + flowChannelWidth / 2, y - chemostatLength / 5 + flowChannelWidth / 2); - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // top left vert - topLeft = new paper.Point(x + chemostatChannelWidth / 2 + (3 * chemostatLength) / 7 - flowChannelWidth / 2, y - chemostatLength / 5 - flowChannelWidth / 2); - bottomRight = new paper.Point(x + chemostatChannelWidth / 2 + (3 * chemostatLength) / 7 + flowChannelWidth / 2, y); - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // top right vert - topLeft = new paper.Point(x + (5 * chemostatLength) / 6 - flowChannelWidth / 2, y - chemostatLength / 5); - bottomRight = new paper.Point(x + (5 * chemostatLength) / 6 + flowChannelWidth / 2, y); - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - serp.rotate(rotation, new paper.Point(x, y)); - serp.fillColor = color; - return serp; - } - - __drawControl(params: { [k: string]: any }) { - const x = params.position[0]; - const y = params.position[1]; - const flowChannelWidth = params.flowChannelWidth; - const controlChannelWidth = params.controlChannelWidth; - const chemostatChannelWidth = params.chemostatChannelWidth; - const volume = params.volume; - const height = params.height; - const radius = params.radius; - const rotation = params.rotation; - const color = params.color; - - const area = volume / height; - const chemostatLength = area / (4 * chemostatChannelWidth); - - const control = new paper.CompoundPath(""); - - const valvelength = 1.5 * chemostatChannelWidth; - const valvewidth = 2 * controlChannelWidth; - const controlSpacing = chemostatLength / 10; - - const controlendpoint = (-7 * chemostatLength) / 8; - const bendDist = chemostatLength / 15; - - // 1 - let topLeft = new paper.Point(x - chemostatLength / 3 - chemostatLength / 5 - controlChannelWidth / 2 - controlSpacing - radius, y + controlendpoint); - let bottomRight = new paper.Point(x - chemostatLength / 3 - chemostatLength / 5 + controlChannelWidth / 2 - controlSpacing - radius, y - chemostatLength / 3 - bendDist); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point( - x - chemostatLength / 3 - chemostatLength / 5 - controlChannelWidth / 2 - controlSpacing - radius, - y - chemostatLength / 3 - bendDist - controlChannelWidth / 2 - ); - bottomRight = new paper.Point(x - chemostatLength / 3 - chemostatLength / 5 - controlSpacing, y - chemostatLength / 3 - bendDist + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point( - x - chemostatLength / 3 - chemostatLength / 5 - controlSpacing - controlChannelWidth / 2, - y - chemostatLength / 3 - bendDist - controlChannelWidth / 2 - ); - bottomRight = new paper.Point(x - chemostatLength / 3 - chemostatLength / 5 - controlSpacing + controlChannelWidth / 2, y - chemostatLength / 3); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x - chemostatLength / 3 - chemostatLength / 5 - controlSpacing - valvewidth / 2, y - chemostatLength / 3 - valvelength / 2); - bottomRight = new paper.Point(x - chemostatLength / 3 - chemostatLength / 5 - controlSpacing + valvewidth / 2, y - chemostatLength / 3 + valvelength / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // 2 - topLeft = new paper.Point(x - chemostatLength / 3 - chemostatLength / 5 - valvelength / 2, y - chemostatLength / 3 - controlSpacing - valvewidth / 2); - bottomRight = new paper.Point(x - chemostatLength / 3 - chemostatLength / 5 + valvelength / 2, y - chemostatLength / 3 - controlSpacing + valvewidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x - chemostatLength / 3 - chemostatLength / 5, y - chemostatLength / 3 - controlSpacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x - chemostatLength / 3 - chemostatLength / 5 + 1.3 * radius, y - chemostatLength / 3 - controlSpacing + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x - chemostatLength / 3 - chemostatLength / 5 + 1.3 * radius - controlChannelWidth / 2, y + controlendpoint); - bottomRight = new paper.Point( - x - chemostatLength / 3 - chemostatLength / 5 + 1.3 * radius + controlChannelWidth / 2, - y - chemostatLength / 3 - controlSpacing + controlChannelWidth / 2 - ); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // 3 - topLeft = new paper.Point(x - chemostatLength / 3 - chemostatLength / 5 + controlSpacing - valvewidth / 2, y - chemostatLength / 3 - valvelength / 2); - bottomRight = new paper.Point(x - chemostatLength / 3 - chemostatLength / 5 + controlSpacing + valvewidth / 2, y - chemostatLength / 3 + valvelength / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x - chemostatLength / 3 - chemostatLength / 5 + controlSpacing - controlChannelWidth / 2, y - chemostatLength / 3 - bendDist); - bottomRight = new paper.Point(x - chemostatLength / 3 - chemostatLength / 5 + controlSpacing + controlChannelWidth / 2, y - chemostatLength / 3); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point( - x - chemostatLength / 3 - chemostatLength / 5 + controlSpacing - controlChannelWidth / 2, - y - chemostatLength / 3 - bendDist - controlChannelWidth / 2 - ); - bottomRight = new paper.Point(x - chemostatLength / 3 - chemostatLength / 5 + 1.7 * radius, y - chemostatLength / 3 - bendDist + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x - chemostatLength / 3 - chemostatLength / 5 + 1.7 * radius - controlChannelWidth / 2, y + controlendpoint); - bottomRight = new paper.Point( - x - chemostatLength / 3 - chemostatLength / 5 + 1.7 * radius + controlChannelWidth / 2, - y - chemostatLength / 3 - bendDist + controlChannelWidth / 2 - ); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // 4 - topLeft = new paper.Point(x - chemostatLength / 3 + chemostatLength / 5 - controlChannelWidth / 2 - controlSpacing - radius, y + controlendpoint); - bottomRight = new paper.Point(x - chemostatLength / 3 + chemostatLength / 5 + controlChannelWidth / 2 - controlSpacing - radius, y - chemostatLength / 3 - bendDist); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point( - x - chemostatLength / 3 + chemostatLength / 5 - controlChannelWidth / 2 - controlSpacing - radius, - y - chemostatLength / 3 - bendDist - controlChannelWidth / 2 - ); - bottomRight = new paper.Point(x - chemostatLength / 3 + chemostatLength / 5 - controlSpacing, y - chemostatLength / 3 - bendDist + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point( - x - chemostatLength / 3 + chemostatLength / 5 - controlSpacing - controlChannelWidth / 2, - y - chemostatLength / 3 - bendDist - controlChannelWidth / 2 - ); - bottomRight = new paper.Point(x - chemostatLength / 3 + chemostatLength / 5 - controlSpacing + controlChannelWidth / 2, y - chemostatLength / 3); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x - chemostatLength / 3 + chemostatLength / 5 - controlSpacing - valvewidth / 2, y - chemostatLength / 3 - valvelength / 2); - bottomRight = new paper.Point(x - chemostatLength / 3 + chemostatLength / 5 - controlSpacing + valvewidth / 2, y - chemostatLength / 3 + valvelength / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // 5 - topLeft = new paper.Point(x - chemostatLength / 3 + chemostatLength / 5 - valvelength / 2, y - chemostatLength / 3 - controlSpacing - valvewidth / 2); - bottomRight = new paper.Point(x - chemostatLength / 3 + chemostatLength / 5 + valvelength / 2, y - chemostatLength / 3 - controlSpacing + valvewidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x - chemostatLength / 3 + chemostatLength / 5, y - chemostatLength / 3 - controlSpacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x - chemostatLength / 3 + chemostatLength / 5 + 1.3 * radius, y - chemostatLength / 3 - controlSpacing + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x - chemostatLength / 3 + chemostatLength / 5 + 1.3 * radius - controlChannelWidth / 2, y + controlendpoint); - bottomRight = new paper.Point( - x - chemostatLength / 3 + chemostatLength / 5 + 1.3 * radius + controlChannelWidth / 2, - y - chemostatLength / 3 - controlSpacing + controlChannelWidth / 2 - ); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // 6 - topLeft = new paper.Point(x - chemostatLength / 3 + chemostatLength / 5 + controlSpacing - valvewidth / 2, y - chemostatLength / 3 - valvelength / 2); - bottomRight = new paper.Point(x - chemostatLength / 3 + chemostatLength / 5 + controlSpacing + valvewidth / 2, y - chemostatLength / 3 + valvelength / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x - chemostatLength / 3 + chemostatLength / 5 + controlSpacing - controlChannelWidth / 2, y - chemostatLength / 3 - bendDist); - bottomRight = new paper.Point(x - chemostatLength / 3 + chemostatLength / 5 + controlSpacing + controlChannelWidth / 2, y - chemostatLength / 3); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point( - x - chemostatLength / 3 + chemostatLength / 5 + controlSpacing - controlChannelWidth / 2, - y - chemostatLength / 3 - bendDist - controlChannelWidth / 2 - ); - bottomRight = new paper.Point(x - chemostatLength / 3 + chemostatLength / 5 + 1.7 * radius, y - chemostatLength / 3 - bendDist + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x - chemostatLength / 3 + chemostatLength / 5 + 1.7 * radius - controlChannelWidth / 2, y + controlendpoint); - bottomRight = new paper.Point( - x - chemostatLength / 3 + chemostatLength / 5 + 1.7 * radius + controlChannelWidth / 2, - y - chemostatLength / 3 - bendDist + controlChannelWidth / 2 - ); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // top left vert - let originx = chemostatChannelWidth / 2 + (3 * chemostatLength) / 7; - let originy = chemostatChannelWidth / 2; - // 7 - topLeft = new paper.Point(x + originx - controlChannelWidth / 2 - controlSpacing - 0.5 * radius, y + controlendpoint); - bottomRight = new paper.Point(x + originx + controlChannelWidth / 2 - controlSpacing - 0.5 * radius, y + originy - bendDist); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx - controlChannelWidth / 2 - controlSpacing - 0.5 * radius, y + originy - bendDist - controlChannelWidth / 2); - bottomRight = new paper.Point(x + originx - controlSpacing, y + originy - bendDist + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx - controlSpacing - controlChannelWidth / 2, y + originy - bendDist - controlChannelWidth / 2); - bottomRight = new paper.Point(x + originx - controlSpacing + controlChannelWidth / 2, y + originy); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx - controlSpacing - valvewidth / 2, y + originy - valvelength / 2); - bottomRight = new paper.Point(x + originx - controlSpacing + valvewidth / 2, y + originy + valvelength / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // 8 - topLeft = new paper.Point(x + originx - valvelength / 2, y + originy - controlSpacing - valvewidth / 2); - bottomRight = new paper.Point(x + originx + valvelength / 2, y + originy - controlSpacing + valvewidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx, y + originy - controlSpacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + originx + 1.3 * radius, y + originy - controlSpacing + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx + 1.3 * radius - controlChannelWidth / 2, y + controlendpoint); - bottomRight = new paper.Point(x + originx + 1.3 * radius + controlChannelWidth / 2, y + originy - controlSpacing + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // 9 - topLeft = new paper.Point(x + originx + controlSpacing - valvewidth / 2, y + originy - valvelength / 2); - bottomRight = new paper.Point(x + originx + controlSpacing + valvewidth / 2, y + originy + valvelength / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx + controlSpacing - controlChannelWidth / 2, y + originy - bendDist); - bottomRight = new paper.Point(x + originx + controlSpacing + controlChannelWidth / 2, y + originy); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx + controlSpacing - controlChannelWidth / 2, y + originy - bendDist - controlChannelWidth / 2); - bottomRight = new paper.Point(x + originx + 1.7 * radius, y + originy - bendDist + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx + 1.7 * radius - controlChannelWidth / 2, y + controlendpoint); - bottomRight = new paper.Point(x + originx + 1.7 * radius + controlChannelWidth / 2, y + originy - bendDist + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // top right vert - originx = (5 * chemostatLength) / 6; - originy = chemostatChannelWidth / 2; - // 10 - topLeft = new paper.Point(x + originx - controlChannelWidth / 2 - controlSpacing - 0.5 * radius, y + controlendpoint); - bottomRight = new paper.Point(x + originx + controlChannelWidth / 2 - controlSpacing - 0.5 * radius, y + originy - bendDist); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx - controlChannelWidth / 2 - controlSpacing - 0.5 * radius, y + originy - bendDist - controlChannelWidth / 2); - bottomRight = new paper.Point(x + originx - controlSpacing, y + originy - bendDist + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx - controlSpacing - controlChannelWidth / 2, y + originy - bendDist - controlChannelWidth / 2); - bottomRight = new paper.Point(x + originx - controlSpacing + controlChannelWidth / 2, y + originy); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx - controlSpacing - valvewidth / 2, y + originy - valvelength / 2); - bottomRight = new paper.Point(x + originx - controlSpacing + valvewidth / 2, y + originy + valvelength / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // 11 - topLeft = new paper.Point(x + originx - valvelength / 2, y + originy - controlSpacing - valvewidth / 2); - bottomRight = new paper.Point(x + originx + valvelength / 2, y + originy - controlSpacing + valvewidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx, y + originy - controlSpacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + originx + 1.3 * radius, y + originy - controlSpacing + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx + 1.3 * radius - controlChannelWidth / 2, y + controlendpoint); - bottomRight = new paper.Point(x + originx + 1.3 * radius + controlChannelWidth / 2, y + originy - controlSpacing + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // 12 - topLeft = new paper.Point(x + originx + controlSpacing - valvewidth / 2, y + originy - valvelength / 2); - bottomRight = new paper.Point(x + originx + controlSpacing + valvewidth / 2, y + originy + valvelength / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx + controlSpacing - controlChannelWidth / 2, y + originy - bendDist); - bottomRight = new paper.Point(x + originx + controlSpacing + controlChannelWidth / 2, y + originy); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx + controlSpacing - controlChannelWidth / 2, y + originy - bendDist - controlChannelWidth / 2); - bottomRight = new paper.Point(x + originx + 1.7 * radius, y + originy - bendDist + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx + 1.7 * radius - controlChannelWidth / 2, y + controlendpoint); - bottomRight = new paper.Point(x + originx + 1.7 * radius + controlChannelWidth / 2, y + originy - bendDist + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // left top - originx = chemostatChannelWidth / 2; - originy = chemostatLength / 5; - - // 13 - topLeft = new paper.Point(x + originx - valvelength / 2, y + originy - controlSpacing - valvewidth / 2); - bottomRight = new paper.Point(x + originx + valvelength / 2, y + originy - controlSpacing + valvewidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx - bendDist - controlChannelWidth / 2, y + originy - controlSpacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + originx, y + originy - controlSpacing + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx - bendDist - controlChannelWidth / 2, y + originy - controlChannelWidth / 2 - controlSpacing - 0.5 * radius); - bottomRight = new paper.Point(x + originx - bendDist + controlChannelWidth / 2, y + originy - controlSpacing); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + controlendpoint, y + originy - controlChannelWidth / 2 - controlSpacing - 0.5 * radius); - bottomRight = new paper.Point(x + originx - bendDist, y + originy + controlChannelWidth / 2 - controlSpacing - 0.5 * radius); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // 14 - topLeft = new paper.Point(x + originx - controlSpacing - valvewidth / 2, y + originy - valvelength / 2); - bottomRight = new paper.Point(x + originx - controlSpacing + valvewidth / 2, y + originy + valvelength / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx - controlSpacing - controlChannelWidth / 2, y + originy); - bottomRight = new paper.Point(x + originx - controlSpacing + controlChannelWidth / 2, y + originy + 1.3 * radius); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + controlendpoint, y + originy + 1.3 * radius - controlChannelWidth / 2); - bottomRight = new paper.Point(x + originx - controlSpacing + controlChannelWidth / 2, y + originy + 1.3 * radius + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // 15 - topLeft = new paper.Point(x + originx - valvelength / 2, y + originy + controlSpacing - valvewidth / 2); - bottomRight = new paper.Point(x + originx + valvelength / 2, y + originy + controlSpacing + valvewidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx - bendDist, y + originy + controlSpacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + originx, y + originy + controlSpacing + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx - bendDist - controlChannelWidth / 2, y + originy + controlSpacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + originx - bendDist + controlChannelWidth / 2, y + originy + 1.7 * radius); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + controlendpoint, y + originy + 1.7 * radius - controlChannelWidth / 2); - bottomRight = new paper.Point(x + originx - bendDist + controlChannelWidth / 2, y + originy + 1.7 * radius + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // left bottom - originx = chemostatChannelWidth / 2; - originy = chemostatLength / 5 + chemostatLength / 2; - - // 16 - topLeft = new paper.Point(x + originx - valvelength / 2, y + originy - controlSpacing - valvewidth / 2); - bottomRight = new paper.Point(x + originx + valvelength / 2, y + originy - controlSpacing + valvewidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx - bendDist - controlChannelWidth / 2, y + originy - controlSpacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + originx, y + originy - controlSpacing + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx - bendDist - controlChannelWidth / 2, y + originy - controlChannelWidth / 2 - controlSpacing - 0.5 * radius); - bottomRight = new paper.Point(x + originx - bendDist + controlChannelWidth / 2, y + originy - controlSpacing); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + controlendpoint, y + originy - controlChannelWidth / 2 - controlSpacing - 0.5 * radius); - bottomRight = new paper.Point(x + originx - bendDist, y + originy + controlChannelWidth / 2 - controlSpacing - 0.5 * radius); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // 17 - topLeft = new paper.Point(x + originx - controlSpacing - valvewidth / 2, y + originy - valvelength / 2); - bottomRight = new paper.Point(x + originx - controlSpacing + valvewidth / 2, y + originy + valvelength / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx - controlSpacing - controlChannelWidth / 2, y + originy); - bottomRight = new paper.Point(x + originx - controlSpacing + controlChannelWidth / 2, y + originy + 1.3 * radius); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + controlendpoint, y + originy + 1.3 * radius - controlChannelWidth / 2); - bottomRight = new paper.Point(x + originx - controlSpacing + controlChannelWidth / 2, y + originy + 1.3 * radius + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // 18 - topLeft = new paper.Point(x + originx - valvelength / 2, y + originy + controlSpacing - valvewidth / 2); - bottomRight = new paper.Point(x + originx + valvelength / 2, y + originy + controlSpacing + valvewidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx - bendDist, y + originy + controlSpacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + originx, y + originy + controlSpacing + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx - bendDist - controlChannelWidth / 2, y + originy + controlSpacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + originx - bendDist + controlChannelWidth / 2, y + originy + 1.7 * radius); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + controlendpoint, y + originy + 1.7 * radius - controlChannelWidth / 2); - bottomRight = new paper.Point(x + originx - bendDist + controlChannelWidth / 2, y + originy + 1.7 * radius + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // right top - originx = chemostatChannelWidth / 2 + chemostatLength; - originy = chemostatChannelWidth / 2 + (2 * chemostatLength) / 5; - - // 19 - topLeft = new paper.Point(x + originx - valvelength / 2, y + originy - controlSpacing - valvewidth / 2); - bottomRight = new paper.Point(x + originx + valvelength / 2, y + originy - controlSpacing + valvewidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx + bendDist - controlChannelWidth / 2, y + originy - controlSpacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + originx, y + originy - controlSpacing + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx + bendDist - controlChannelWidth / 2, y + originy - controlChannelWidth / 2 - controlSpacing - 0.5 * radius); - bottomRight = new paper.Point(x + originx + bendDist + controlChannelWidth / 2, y + originy - controlSpacing + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + 2 * chemostatLength, y + originy - controlChannelWidth / 2 - controlSpacing - 0.5 * radius); - bottomRight = new paper.Point(x + originx + bendDist, y + originy + controlChannelWidth / 2 - controlSpacing - 0.5 * radius); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // 20 - topLeft = new paper.Point(x + originx + controlSpacing - valvewidth / 2, y + originy - valvelength / 2); - bottomRight = new paper.Point(x + originx + controlSpacing + valvewidth / 2, y + originy + valvelength / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx + controlSpacing - controlChannelWidth / 2, y + originy); - bottomRight = new paper.Point(x + originx + controlSpacing + controlChannelWidth / 2, y + originy + 1.3 * radius); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + 2 * chemostatLength, y + originy + 1.3 * radius - controlChannelWidth / 2); - bottomRight = new paper.Point(x + originx + controlSpacing - controlChannelWidth / 2, y + originy + 1.3 * radius + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // 21 - topLeft = new paper.Point(x + originx - valvelength / 2, y + originy + controlSpacing - valvewidth / 2); - bottomRight = new paper.Point(x + originx + valvelength / 2, y + originy + controlSpacing + valvewidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx + bendDist, y + originy + controlSpacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + originx, y + originy + controlSpacing + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx + bendDist - controlChannelWidth / 2, y + originy + controlSpacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + originx + bendDist + controlChannelWidth / 2, y + originy + 1.7 * radius); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + 2 * chemostatLength, y + originy + 1.7 * radius - controlChannelWidth / 2); - bottomRight = new paper.Point(x + originx + bendDist - controlChannelWidth / 2, y + originy + 1.7 * radius + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // right bottom - originx = chemostatChannelWidth / 2 + chemostatLength; - originy = chemostatChannelWidth / 2 + (4 * chemostatLength) / 5; - - // 22 - topLeft = new paper.Point(x + originx - valvelength / 2, y + originy - controlSpacing - valvewidth / 2); - bottomRight = new paper.Point(x + originx + valvelength / 2, y + originy - controlSpacing + valvewidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx + bendDist - controlChannelWidth / 2, y + originy - controlSpacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + originx, y + originy - controlSpacing + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx + bendDist - controlChannelWidth / 2, y + originy - controlChannelWidth / 2 - controlSpacing - 0.5 * radius); - bottomRight = new paper.Point(x + originx + bendDist + controlChannelWidth / 2, y + originy - controlSpacing + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + 2 * chemostatLength, y + originy - controlChannelWidth / 2 - controlSpacing - 0.5 * radius); - bottomRight = new paper.Point(x + originx + bendDist, y + originy + controlChannelWidth / 2 - controlSpacing - 0.5 * radius); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // 23 - topLeft = new paper.Point(x + originx + controlSpacing - valvewidth / 2, y + originy - valvelength / 2); - bottomRight = new paper.Point(x + originx + controlSpacing + valvewidth / 2, y + originy + valvelength / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx + controlSpacing - controlChannelWidth / 2, y + originy); - bottomRight = new paper.Point(x + originx + controlSpacing + controlChannelWidth / 2, y + originy + 1.3 * radius); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + 2 * chemostatLength, y + originy + 1.3 * radius - controlChannelWidth / 2); - bottomRight = new paper.Point(x + originx + controlSpacing - controlChannelWidth / 2, y + originy + 1.3 * radius + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // 24 - topLeft = new paper.Point(x + originx - valvelength / 2, y + originy + controlSpacing - valvewidth / 2); - bottomRight = new paper.Point(x + originx + valvelength / 2, y + originy + controlSpacing + valvewidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx + bendDist, y + originy + controlSpacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + originx, y + originy + controlSpacing + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx + bendDist - controlChannelWidth / 2, y + originy + controlSpacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + originx + bendDist + controlChannelWidth / 2, y + originy + 1.7 * radius); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + 2 * chemostatLength, y + originy + 1.7 * radius - controlChannelWidth / 2); - bottomRight = new paper.Point(x + originx + bendDist - controlChannelWidth / 2, y + originy + 1.7 * radius + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // bottom left - originx = chemostatChannelWidth / 2 + chemostatLength / 4; - originy = chemostatLength + chemostatChannelWidth / 2; - - // 25 - topLeft = new paper.Point(x + originx - 0.3 * controlSpacing - valvewidth / 2, y + originy - valvelength / 2); - bottomRight = new paper.Point(x + originx - 0.3 * controlSpacing + valvewidth / 2, y + originy + valvelength / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx - controlChannelWidth / 2 - 0.3 * controlSpacing, y + originy); - bottomRight = new paper.Point(x + originx + controlChannelWidth / 2 - 0.3 * controlSpacing, y + 2 * chemostatLength); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // 26 - topLeft = new paper.Point(x + originx - valvelength / 2, y + originy + controlSpacing - valvewidth / 2); - bottomRight = new paper.Point(x + originx + valvelength / 2, y + originy + controlSpacing + valvewidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx, y + originy + controlSpacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + originx + 0.5 * controlSpacing, y + originy + controlSpacing + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx + 0.5 * controlSpacing - controlChannelWidth / 2, y + originy + controlSpacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + originx + 0.5 * controlSpacing + controlChannelWidth / 2, y + 2 * chemostatLength); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // 27 - topLeft = new paper.Point(x + originx + 0.3 * controlSpacing - valvewidth / 2, y + originy - valvelength / 2); - bottomRight = new paper.Point(x + originx + 0.3 * controlSpacing + valvewidth / 2, y + originy + valvelength / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx + 0.3 * controlSpacing - controlChannelWidth / 2, y + originy); - bottomRight = new paper.Point(x + originx + 0.3 * controlSpacing + controlChannelWidth / 2, y + originy + bendDist); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx + 0.3 * controlSpacing - controlChannelWidth / 2, y + originy + bendDist - controlChannelWidth / 2); - bottomRight = new paper.Point(x + originx + 0.3 * controlSpacing + 0.4 * controlSpacing, y + originy + bendDist + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx - controlChannelWidth / 2 + 0.4 * controlSpacing + 0.3 * controlSpacing, y + originy - controlChannelWidth / 2 + bendDist); - bottomRight = new paper.Point(x + originx + controlChannelWidth / 2 + 0.4 * controlSpacing + 0.3 * controlSpacing, y + 2 * chemostatLength); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // bottom middle - originx = chemostatChannelWidth / 2 + (3 * chemostatLength) / 7; - originy = chemostatLength + chemostatChannelWidth / 2; - - // 28 - topLeft = new paper.Point(x + originx - 0.3 * controlSpacing - valvewidth / 2, y + originy - valvelength / 2); - bottomRight = new paper.Point(x + originx - 0.3 * controlSpacing + valvewidth / 2, y + originy + valvelength / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx - controlChannelWidth / 2 - 0.3 * controlSpacing, y + originy); - bottomRight = new paper.Point(x + originx + controlChannelWidth / 2 - 0.3 * controlSpacing, y + 2 * chemostatLength); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // 29 - topLeft = new paper.Point(x + originx - valvelength / 2, y + originy - controlSpacing - valvewidth / 2); - bottomRight = new paper.Point(x + originx + valvelength / 2, y + originy - controlSpacing + valvewidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx, y + originy - controlSpacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + originx - 0.5 * controlSpacing, y + originy - controlSpacing + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx - 0.5 * controlSpacing - controlChannelWidth / 2, y + originy - controlSpacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + originx - 0.5 * controlSpacing + controlChannelWidth / 2, y + 2 * chemostatLength); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // 30 - topLeft = new paper.Point(x + originx + 0.3 * controlSpacing - valvewidth / 2, y + originy - valvelength / 2); - bottomRight = new paper.Point(x + originx + 0.3 * controlSpacing + valvewidth / 2, y + originy + valvelength / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx - controlChannelWidth / 2 + 0.3 * controlSpacing, y + originy); - bottomRight = new paper.Point(x + originx + controlChannelWidth / 2 + 0.3 * controlSpacing, y + 2 * chemostatLength); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // 31 - topLeft = new paper.Point(x + originx + 0.55 * controlSpacing - valvewidth / 2, y + originy - valvelength); - bottomRight = new paper.Point(x + originx + 0.55 * controlSpacing + valvewidth / 2, y + originy + valvelength); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx + 0.55 * controlSpacing - controlChannelWidth / 2, y + originy); - bottomRight = new paper.Point(x + originx + 0.55 * controlSpacing + controlChannelWidth / 2, y + 2 * chemostatLength); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // 32 - topLeft = new paper.Point(x + originx + 0.85 * controlSpacing - valvewidth / 2, y + originy - valvelength); - bottomRight = new paper.Point(x + originx + 0.85 * controlSpacing + valvewidth / 2, y + originy + valvelength); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx + 0.85 * controlSpacing - controlChannelWidth / 2, y + originy); - bottomRight = new paper.Point(x + originx + 0.85 * controlSpacing + controlChannelWidth / 2, y + 2 * chemostatLength); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // 33 - topLeft = new paper.Point(x + originx + 1.15 * controlSpacing - valvewidth / 2, y + originy - valvelength); - bottomRight = new paper.Point(x + originx + 1.15 * controlSpacing + valvewidth / 2, y + originy + valvelength); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx + 1.15 * controlSpacing - controlChannelWidth / 2, y + originy); - bottomRight = new paper.Point(x + originx + 1.15 * controlSpacing + controlChannelWidth / 2, y + 2 * chemostatLength); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // bottom right - originx = chemostatChannelWidth / 2 + (3 * chemostatLength) / 5; - originy = chemostatLength + chemostatChannelWidth / 2; - - // 34 - topLeft = new paper.Point(x + originx - 0.3 * controlSpacing - valvewidth / 2, y + originy - valvelength / 2); - bottomRight = new paper.Point(x + originx - 0.3 * controlSpacing + valvewidth / 2, y + originy + valvelength / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx - controlChannelWidth / 2 - 0.3 * controlSpacing, y + originy); - bottomRight = new paper.Point(x + originx + controlChannelWidth / 2 - 0.3 * controlSpacing, y + 2 * chemostatLength); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // 35 - topLeft = new paper.Point(x + originx - valvelength / 2, y + originy + controlSpacing - valvewidth / 2); - bottomRight = new paper.Point(x + originx + valvelength / 2, y + originy + controlSpacing + valvewidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx, y + originy + controlSpacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + originx + 0.5 * controlSpacing, y + originy + controlSpacing + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx + 0.5 * controlSpacing - controlChannelWidth / 2, y + originy + controlSpacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + originx + 0.5 * controlSpacing + controlChannelWidth / 2, y + 2 * chemostatLength); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // 36 - topLeft = new paper.Point(x + originx + 0.3 * controlSpacing - valvewidth / 2, y + originy - valvelength / 2); - bottomRight = new paper.Point(x + originx + 0.3 * controlSpacing + valvewidth / 2, y + originy + valvelength / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx + 0.3 * controlSpacing - controlChannelWidth / 2, y + originy); - bottomRight = new paper.Point(x + originx + 0.3 * controlSpacing + controlChannelWidth / 2, y + originy + bendDist); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx + 0.3 * controlSpacing - controlChannelWidth / 2, y + originy + bendDist - controlChannelWidth / 2); - bottomRight = new paper.Point(x + originx + 0.3 * controlSpacing + 0.4 * controlSpacing, y + originy + bendDist + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + originx - controlChannelWidth / 2 + 0.4 * controlSpacing + 0.3 * controlSpacing, y + originy - controlChannelWidth / 2 + bendDist); - bottomRight = new paper.Point(x + originx + controlChannelWidth / 2 + 0.4 * controlSpacing + 0.3 * controlSpacing, y + 2 * chemostatLength); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - control.rotate(rotation, new paper.Point(x, y)); - control.fillColor = color; - return control; - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - const serp = this.__drawFlow(params); - serp.addChild(this.__drawControl(params)); - - serp.fillColor!.alpha = 0.5; - return serp; - } -} diff --git a/src/app/library/circleValve.ts b/src/app/library/circleValve.ts deleted file mode 100644 index c9f63ca9..00000000 --- a/src/app/library/circleValve.ts +++ /dev/null @@ -1,99 +0,0 @@ -import Template from "./template"; -import paper from "paper"; - -export default class CircleValve extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - radius1: "Float", - radius2: "Float", - height: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - radius1: 1.4 * 1000, - radius2: 1.2 * 1000, - height: 250 - }; - - this.__units = { - componentSpacing: "μm", - radius1: "μm", - radius2: "μm", - height: "μm" - }; - - this.__minimum = { - componentSpacing: 0, - radius1: 10, - radius2: 10, - height: 10 - }; - - this.__maximum = { - componentSpacing: 10000, - radius1: 2000, - radius2: 2000, - height: 1200 - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - radius1: "portRadius", - radius2: "radius2" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - radius1: "portRadius", - radius2: "radius2" - }; - - this.__placementTool = "componentPositionTool"; - - this.__toolParams = { - position: "position" - }; - - this.__renderKeys = ["CONTROL"]; - - this.__mint = "CIRCLE VALVE"; - - this.__zOffsetKeys = { - CONTROL: "height" - }; - - this.__substrateOffset = { - CONTROL: "+1" - }; - } - - render2D(params: { [k: string]: any }, key: string) { - const position = params.position; - const radius = params.portRadius; - const color1 = params.color; - const pos = new paper.Point(position[0], position[1]); - const outerCircle = new paper.Path.Circle(pos, radius); - outerCircle.fillColor = color1; - return outerCircle; - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - if (key === null) { - key = this.__renderKeys[0]; - } - const render = this.render2D(params, key); - render.fillColor!.alpha = 0.5; - return render; - } -} diff --git a/src/app/library/connection.ts b/src/app/library/connection.ts deleted file mode 100644 index ecb1e89d..00000000 --- a/src/app/library/connection.ts +++ /dev/null @@ -1,137 +0,0 @@ -import Template from "./template"; -import paper from "paper"; - -export default class Connection extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - start: "Point", - end: "Point", - wayPoints: "PointArray", - segments: "SegmentArray" - }; - - this.__heritable = { - connectionSpacing: "Float", - channelWidth: "Float", - height: "Float" - }; - - this.__defaults = { - connectionSpacing: 1600, - channelWidth: 0.8 * 1000, - height: 250 - }; - - this.__units = { - connectionSpacing: "μm", - channelWidth: "μm", - height: "μm" - }; - - this.__minimum = { - connectionSpacing: 0, - channelWidth: 3, - height: 10 - }; - - this.__maximum = { - connectionSpacing: 10000, - channelWidth: 12000, - height: 1200 - }; - - this.__featureParams = { - connectionSpacing: "connectionSpacing", - start: "start", - end: "end", - wayPoints: "wayPoints", - channelWidth: "channelWidth", - segments: "segments", - height: "height" - }; - - this.__targetParams = { - connectionSpacing: "connectionSpacing", - wayPoints: "wayPoints", - channelWidth: "channelWidth", - segments: "segments", - height: "height" - }; - - this.__placementTool = "ConnectionTool"; - - this.__toolParams = { - start: "start", - end: "end" - }; - - this.__renderKeys = ["FLOW"]; - - this.__mint = "CHANNEL"; - - this.__zOffsetKeys = { - FLOW: "height" - }; - - this.__substrateOffset = { - FLOW: "0" - }; - } - - render2D(params: { [k: string]: any }, key: string) { - const start = params.start; - const end = params.end; - const color = params.color; - const width = params.width; - const wayPoints = params.wayPoints; - const channelWidth = params.channelWidth; - const segments = params.segments; - const connectionpath = new paper.CompoundPath(""); - let startpoint, endpoint; - - let p1, p2; - - for (const i in segments) { - const segment = segments[i]; - p1 = segment[0]; - p2 = segment[1]; - startpoint = new paper.Point(p1[0], p1[1]); - endpoint = new paper.Point(p2[0], p2[1]); - this.__drawStraightConnection(connectionpath, startpoint, endpoint, channelWidth); - } - - connectionpath.fillColor = color; - return connectionpath; - } - - __drawStraightConnection(compoundpath: paper.CompoundPath, startpoint: paper.Point, endpoint: paper.Point, channelWidth: number): void { - // edit the points - const vec = endpoint.subtract(startpoint); - const rec = new paper.Path.Rectangle({ - point: startpoint, - radius: channelWidth / 2, - size: [vec.length + channelWidth, channelWidth] - }); - rec.translate(([-channelWidth / 2, -channelWidth / 2] as unknown) as paper.Point); - rec.rotate(vec.angle, startpoint); - - compoundpath.addChild(rec); - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - const thickness = params.channelWidth / 5; - const length = params.channelWidth; - const x = params.position[0]; - const y = params.position[1]; - const color = params.color; - let chair = new paper.Path.Rectangle(new paper.Rectangle(x - length / 2, y - thickness / 2, length, thickness)); - let chairtarget = chair.unite(new paper.Path.Rectangle(new paper.Rectangle(x - thickness / 2, y - length / 2, thickness, length))); - chairtarget.fillColor = color; - chairtarget.fillColor!.alpha = 0.5; - return chairtarget; - } -} diff --git a/src/app/library/curvedMixer.ts b/src/app/library/curvedMixer.ts deleted file mode 100755 index b9036a53..00000000 --- a/src/app/library/curvedMixer.ts +++ /dev/null @@ -1,201 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class CurvedMixer extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - bendSpacing: "Float", - numberOfBends: "Float", - channelWidth: "Float", - bendLength: "Float", - rotation: "Float", - height: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - rotation: 0, - channelWidth: 0.8 * 1000, - bendSpacing: 1.23 * 1000, - numberOfBends: 1, - bendLength: 2.46 * 1000, - height: 250 - }; - - this.__units = { - componentSpacing: "μm", - rotation: "°", - bendSpacing: "μm", - numberOfBends: "", - channelWidth: "μm", - bendLength: "μm", - height: "μm" - }; - - this.__minimum = { - componentSpacing: 0, - rotation: 0, - channelWidth: 10, - bendSpacing: 10, - numberOfBends: 1, - bendLength: 10, - height: 10 - }; - - this.__maximum = { - componentSpacing: 10000, - rotation: 360, - channelWidth: 2000, - bendSpacing: 6000, - numberOfBends: 20, - bendLength: 12 * 1000, - height: 1200 - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - channelWidth: "channelWidth", - bendSpacing: "bendSpacing", - numberOfBends: "numberOfBends", - rotation: "rotation", - bendLength: "bendLength" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - channelWidth: "channelWidth", - bendSpacing: "bendSpacing", - numberOfBends: "numberOfBends", - rotation: "rotation", - bendLength: "bendLength" - }; - - this.__placementTool = "componentPositionTool"; - - this.__toolParams = { - position: "position" - }; - - this.__renderKeys = ["FLOW"]; - - this.__mint = "CURVED MIXER"; - - this.__zOffsetKeys = { - FLOW: "height" - }; - - this.__substrateOffset = { - FLOW: "0" - }; - } - - getPorts(params: { [k: string]: any }) { - const channelWidth = params.channelWidth; - const bendLength = params.bendLength; - const bendSpacing = params.bendSpacing; - const numberOfBends = params.numberOfBends; - - const ports = []; - - ports.push(new ComponentPort(bendLength / 2 + channelWidth, 0, "1", LogicalLayerType.FLOW)); - - ports.push(new ComponentPort(bendLength / 2 + channelWidth, (2 * numberOfBends + 1) * channelWidth + 2 * numberOfBends * bendSpacing, "2", LogicalLayerType.FLOW)); - - return ports; - } - - render2D(params: { [k: string]: any }, key: string) { - const channelWidth = params.channelWidth; - const bendLength = params.bendLength; - const bendSpacing = params.bendSpacing; - const rotation = params.rotation; - const numBends = params.numberOfBends; - const x = params.position[0]; - const y = params.position[1]; - const color = params.color; - const segHalf = bendLength / 2 + channelWidth; - const segLength = bendLength + 2 * channelWidth; - const segBend = bendSpacing + 2 * channelWidth; - const vRepeat = 2 * bendSpacing + 2 * channelWidth; - const vOffset = bendSpacing + channelWidth; - const hOffset = bendLength / 2 + channelWidth / 2; - const serp = new paper.CompoundPath(""); - - // draw first segment - let toprect: paper.Rectangle | paper.PathItem = new paper.Path.Rectangle(new paper.Rectangle(x + channelWidth - 1, y, bendLength / 2 + channelWidth / 2 + 1, channelWidth)); - (toprect as any).closed = true; - for (let i = 0; i < numBends; i++) { - // draw left curved segment - let leftCurve: paper.Path.Arc | paper.PathItem = new paper.Path.Arc({ - from: [x + channelWidth, y + vRepeat * i], - through: [x + channelWidth - (channelWidth + bendSpacing / 2), y + vRepeat * i + bendSpacing / 2 + channelWidth], - to: [x + channelWidth, y + vRepeat * i + bendSpacing + 2 * channelWidth] - }); - (leftCurve as any).closed = true; - const leftCurveSmall = new paper.Path.Arc({ - from: [x + channelWidth, y + vRepeat * i + bendSpacing + channelWidth], - through: [x + channelWidth - bendSpacing / 2, y + vRepeat * i + bendSpacing / 2 + channelWidth], - to: [x + channelWidth, y + vRepeat * i + channelWidth] - }); - leftCurveSmall.closed = true; - leftCurve = leftCurve.subtract(leftCurveSmall); - toprect = toprect.unite(leftCurve); - // serp.addChild(leftCurve); - // draw horizontal segment - let hseg = new paper.Path.Rectangle(new paper.Rectangle(x + channelWidth - 1, y + vOffset + vRepeat * i, bendLength + 2, channelWidth)); - toprect = toprect.unite(hseg); - // draw right curved segment - let rightCurve: paper.Path.Arc | paper.PathItem = new paper.Path.Arc({ - from: [x + channelWidth + bendLength, y + vOffset + vRepeat * i], - through: [x + channelWidth + bendLength + (channelWidth + bendSpacing / 2), y + vOffset + vRepeat * i + bendSpacing / 2 + channelWidth], - to: [x + channelWidth + bendLength, y + vOffset + vRepeat * i + bendSpacing + 2 * channelWidth] - }); - (rightCurve as any).closed = true; - const rightCurveSmall = new paper.Path.Arc({ - from: [x + channelWidth + bendLength, y + vOffset + vRepeat * i + bendSpacing + channelWidth], - through: [x + channelWidth + bendLength + bendSpacing / 2, y + vOffset + vRepeat * i + bendSpacing / 2 + channelWidth], - to: [x + channelWidth + bendLength, y + vOffset + vRepeat * i + channelWidth] - }); - rightCurveSmall.closed = true; - rightCurve = rightCurve.subtract(rightCurveSmall); - toprect = toprect.unite(rightCurve); - - if (i === numBends - 1) { - // draw half segment to close - hseg = new paper.Path.Rectangle(new paper.Rectangle(x + channelWidth / 2 + bendLength / 2, y + vRepeat * (i + 1), (bendLength + channelWidth) / 2 + 1, channelWidth)); - toprect = toprect.unite(hseg); - } else { - // draw full segment - hseg = new paper.Path.Rectangle(new paper.Rectangle(x + channelWidth - 1, y + vRepeat * (i + 1), bendLength + 2, channelWidth)); - toprect = toprect.unite(hseg); - } - toprect = toprect.unite(hseg); - } - serp.addChild(toprect); - - serp.fillColor = color; - serp.rotate(rotation, new paper.Point(x, y)); - return serp; - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - if (key === null) { - key = this.__renderKeys[0]; - } - const render = this.render2D(params, key); - render.fillColor!.alpha = 0.5; - return render; - } -} diff --git a/src/app/library/diamondReactionChamber.ts b/src/app/library/diamondReactionChamber.ts deleted file mode 100755 index 2c087f4b..00000000 --- a/src/app/library/diamondReactionChamber.ts +++ /dev/null @@ -1,149 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class DiamondReactionChamber extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - rotation: "Float", - channelWidth: "Float", - length: "Float", - width: "Float", - height: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - rotation: 0, - channelWidth: 0.8 * 1000, - width: 1.23 * 1000, - length: 4.92 * 1000, - height: 250 - }; - - this.__units = { - componentSpacing: "μm", - rotation: "°", - channelWidth: "μm", - length: "μm", - width: "μm", - height: "μm" - }; - - this.__minimum = { - componentSpacing: 0, - channelWidth: 10, - width: 30, - length: 120, - height: 10, - rotation: 0 - }; - - this.__maximum = { - componentSpacing: 10000, - channelWidth: 2000, - width: 6000, - length: 24 * 1000, - height: 1200, - rotation: 360 - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - rotation: "rotation", - channelWidth: "channelWidth", - length: "length", - width: "width" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - channelWidth: "channelWidth", - length: "length", - width: "width", - rotation: "rotation" - }; - - this.__placementTool = "componentPositionTool"; - - this.__toolParams = { - position: "position" - }; - - this.__renderKeys = ["FLOW"]; - - this.__mint = "DIAMOND REACTION CHAMBER"; - - this.__zOffsetKeys = { - FLOW: "height" - }; - - this.__substrateOffset = { - FLOW: "0" - }; - } - - getPorts(params: { [k: string]: any }) { - const channelWidth = params.channelWidth; - const l = params.length; - const w = params.width; - - const ports = []; - - ports.push(new ComponentPort(-l / 2, 0, "1", LogicalLayerType.FLOW)); - - ports.push(new ComponentPort(l / 2, 0, "2", LogicalLayerType.FLOW)); - - return ports; - } - - render2D(params: { [k: string]: any }, key: string) { - const position = params.position; - const px = position[0]; - const py = position[1]; - const cw = params.channelWidth; - const l = params.length; - const w = params.width; - const rotation = params.rotation; - console.log("Rotation", rotation); - const color = params.color; - let p0, p1, p2, p3, p4, p5; - p0 = [px - l / 2, py - cw / 2]; - p1 = [px - l / 2, py + cw / 2]; - p2 = [px, py + w + cw / 2]; - p3 = [px + l / 2, py + cw / 2]; - p4 = [px + l / 2, py - cw / 2]; - p5 = [px, py - cw / 2 - w]; - const hex = new paper.Path(); - hex.add(new paper.Point(p0)); - hex.add(new paper.Point(p1)); - hex.add(new paper.Point(p2)); - hex.add(new paper.Point(p3)); - hex.add(new paper.Point(p4)); - hex.add(new paper.Point(p5)); - hex.closed = true; - hex.rotate(rotation, new paper.Point(px, py)); - hex.fillColor = color; - return hex; - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - if (key === null) { - key = this.__renderKeys[0]; - } - const render = this.render2D(params, key); - render.fillColor!.alpha = 0.5; - return render; - } -} diff --git a/src/app/library/dogboneInsert.ts b/src/app/library/dogboneInsert.ts deleted file mode 100644 index 274d21fb..00000000 --- a/src/app/library/dogboneInsert.ts +++ /dev/null @@ -1,191 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class DogboneInsert extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - rotation: "Float", - length: "Float", - innerRadius: "Float", - outerRadius: "Float", - height: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - rotation: 0, - innerRadius: 400, - outerRadius: 800, - length: 7200, - height: 250 - }; - - this.__units = { - componentSpacing: "μm", - rotation: "°", - length: "μm", - innerRadius: "μm", - outerRadius: "μm", - height: "μm" - }; - - this.__minimum = { - componentSpacing: 0, - innerRadius: 1, - outerRadius: 1, - length: 120, - height: 10, - rotation: 0 - }; - - this.__maximum = { - componentSpacing: 10000, - innerRadius: 1000, - outerRadius: 1000, - length: 24 * 1000, - height: 1200, - rotation: 360 - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - rotation: "rotation", - length: "length", - innerRadius: "innerRadius", - outerRadius: "outerRadius", - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - length: "length", - innerRadius: "innerRadius", - outerRadius: "outerRadius", - rotation: "rotation" - }; - - this.__placementTool = "componentPositionTool"; - - this.__toolParams = { - position: "position" - }; - - this.__renderKeys = ["FLOW"]; - - this.__mint = "DOGBONE INSERT"; - - this.__zOffsetKeys = { - FLOW: "height" - }; - - this.__substrateOffset = { - FLOW: "0" - }; - } - - getPorts(params: { [k: string]: any }) { - const l = params.length; - - const ports = []; - - ports.push(new ComponentPort(-l / 2, 0, "1", LogicalLayerType.FLOW)); - - ports.push(new ComponentPort(l / 2, 0, "2", LogicalLayerType.FLOW)); - - return ports; - } - - render2D(params: { [k: string]: any }, key: string): paper.CompoundPath { - const position = params.position; - const px = position[0]; - const py = position[1]; - const length = params.length; - const innerRadius = params.innerRadius; - const outerRadius = params.outerRadius; - const rotation = params.rotation; - const color = params.color; - - const fulllength = length + innerRadius * 2 + outerRadius * 2; - const width = innerRadius * 2 + outerRadius * 4; - - const serp: paper.CompoundPath = new paper.CompoundPath([]); - - let insert = new paper.PathItem; - - // Produce rectangle - const rect2 = new paper.Path.Rectangle(new paper.Point(px - fulllength / 2 + outerRadius, py - width / 2), new paper.Size(fulllength - 2 * outerRadius, width)); - - // Add half circles to ends - // Left side - let curve: paper.Path.Arc | paper.PathItem = new paper.Path.Arc({ - from: [px - fulllength / 2 + outerRadius, py + width / 2], - through: [px - fulllength / 2, py + width / 2 - outerRadius], - to: [px - fulllength / 2 + outerRadius, py + innerRadius] - }); - (curve as any).closed = true; - insert = rect2.unite(curve); - curve = new paper.Path.Arc({ - from: [px - fulllength / 2 + outerRadius, py - width / 2], - through: [px - fulllength / 2, py - width / 2 + outerRadius], - to: [px - fulllength / 2 + outerRadius, py - innerRadius] - }); - (curve as any).closed = true; - insert = insert.unite(curve); - //Right side - curve = new paper.Path.Arc({ - from: [px + fulllength / 2 - outerRadius, py + width / 2], - through: [px + fulllength / 2, py + width / 2 - outerRadius], - to: [px + fulllength / 2 - outerRadius, py + innerRadius] - }); - (curve as any).closed = true; - insert = insert.unite(curve); - curve = new paper.Path.Arc({ - from: [px + fulllength / 2 - outerRadius, py - width / 2], - through: [px + fulllength / 2, py - width / 2 + outerRadius], - to: [px + fulllength / 2 - outerRadius, py - innerRadius] - }); - (curve as any).closed = true; - insert = insert.unite(curve); - - // Subtract half circles - curve = new paper.Path.Arc({ - from: [px - fulllength / 2 + outerRadius, py + innerRadius], - through: [px - fulllength / 2 + innerRadius + outerRadius, py], - to: [px - fulllength / 2 + outerRadius, py - innerRadius] - }); - (curve as any).closed = true; - insert = insert.subtract(curve); - curve = new paper.Path.Arc({ - from: [px + fulllength / 2 - outerRadius, py + innerRadius], - through: [px + fulllength / 2 - innerRadius - outerRadius, py], - to: [px + fulllength / 2 - outerRadius, py - innerRadius] - }); - (curve as any).closed = true; - insert = insert.subtract(curve); - - serp.addChild(insert); - serp.fillColor = color; - serp.rotate(rotation, new paper.Point(px, py)); - return serp; - } - - render2DTarget(key: string | null, params: { [k: string]: any }): paper.CompoundPath { - if (key === null) { - key = this.__renderKeys[0]; - } - const render = this.render2D(params, key); - render.fillColor!.alpha = 0.5; - return render; - } -} diff --git a/src/app/library/dropletGenerator.ts b/src/app/library/dropletGenerator.ts deleted file mode 100644 index 018e4e03..00000000 --- a/src/app/library/dropletGenerator.ts +++ /dev/null @@ -1,213 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class DropletGenerator extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - orificeSize: "Float", - orificeLength: "Float", - oilInputWidth: "Float", - waterInputWidth: "Float", - outputWidth: "Float", - outputLength: "Float", - height: "Float", - rotation: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - orificeSize: 0.2 * 1000, - orificeLength: 0.4 * 1000, - oilInputWidth: 0.8 * 1000, - waterInputWidth: 0.6 * 1000, - outputWidth: 0.6 * 1000, - outputLength: 0.6 * 1000, - height: 250, - rotation: 0 - }; - - this.__units = { - componentSpacing: "μm", - orificeSize: "μm", - height: "μm", - orificeLength: "μm", - oilInputWidth: "μm", - waterInputWidth: "μm", - outputWidth: "μm", - outputLength: "μm", - rotation: "°" - }; - - this.__minimum = { - componentSpacing: 0, - orificeSize: 10, - orificeLength: 10, - oilInputWidth: 10, - waterInputWidth: 10, - outputWidth: 10, - outputLength: 10, - height: 10, - rotation: 0 - }; - - this.__maximum = { - componentSpacing: 10000, - orificeSize: 2000, - orificeLength: 2000, - oilInputWidth: 2000, - waterInputWidth: 2000, - outputWidth: 2000, - outputLength: 2000, - height: 1200, - rotation: 360 - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - orificeSize: "orificeSize", - orificeLength: "orificeLength", - oilInputWidth: "oilInputWidth", - waterInputWidth: "waterInputWidth", - outputWidth: "outputWidth", - outputLength: "outputLength", - height: "height", - rotation: "rotation" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - orificeSize: "orificeSize", - orificeLength: "orificeLength", - oilInputWidth: "oilInputWidth", - waterInputWidth: "waterInputWidth", - outputWidth: "outputWidth", - outputLength: "outputLength", - height: "height", - rotation: "rotation" - }; - - this.__placementTool = "componentPositionTool"; - - this.__toolParams = { - position: "position" - }; - - this.__renderKeys = ["FLOW"]; - - this.__mint = "NOZZLE DROPLET GENERATOR"; - - this.__zOffsetKeys = { - FLOW: "height" - }; - - this.__substrateOffset = { - FLOW: "0" - }; - } - - getPorts(params: { [k: string]: any }) { - const orificeSize = params.orificeSize; - const orificeLength = params.orificeLength; - const oilInputWidth = params.oilInputWidth; - const waterInputWidth = params.waterInputWidth; - const outputWidth = params.outputWidth; - const outputLength = params.outputLength; - - const ports = []; - - // Oil Top - ports.push(new ComponentPort(oilInputWidth / 2, -waterInputWidth / 2, "1", LogicalLayerType.FLOW)); - - // Out - ports.push(new ComponentPort(oilInputWidth + orificeLength + outputLength, 0, "2", LogicalLayerType.FLOW)); - - // Oil Bottom - ports.push(new ComponentPort(oilInputWidth / 2, waterInputWidth / 2, "3", LogicalLayerType.FLOW)); - - // Input - ports.push(new ComponentPort(0, 0, "4", LogicalLayerType.FLOW)); - - return ports; - } - - render2D(params: { [k: string]: any }, key = "FLOW") { - const pos = params.position; - const x = pos[0]; - const y = pos[1]; - const color = params.color; - const orificeSize = params.orificeSize; - const orificeLength = params.orificeLength; - const oilInputWidth = params.oilInputWidth; - const waterInputWidth = params.waterInputWidth; - const outputWidth = params.outputWidth; - const outputLength = params.outputLength; - const rotation = params.rotation; - - const ret = new paper.Path(); - - const p1 = new paper.Point(x, y - waterInputWidth / 2); - - const p2 = new paper.Point(p1.x + oilInputWidth, p1.y); - - const p3 = new paper.Point(p2.x, p2.y + (waterInputWidth / 2 - orificeSize / 2)); - - const p4 = new paper.Point(p3.x + orificeLength, p3.y); - - const p5 = new paper.Point(p4.x, p4.y - (outputWidth / 2 - orificeSize / 2)); - - const p6 = new paper.Point(p5.x + outputLength, p5.y); - - const p7 = new paper.Point(p6.x, p6.y + outputWidth); - - const p8 = new paper.Point(p7.x - outputLength, p7.y); - - const p9 = new paper.Point(p8.x, p8.y - (outputWidth / 2 - orificeSize / 2)); - - const p10 = new paper.Point(p9.x - orificeLength, p9.y); - - const p11 = new paper.Point(p10.x, p10.y + (waterInputWidth / 2 - orificeSize / 2)); - - const p12 = new paper.Point(p11.x - oilInputWidth, p11.y); - - ret.add(p1); - ret.add(p2); - ret.add(p3); - ret.add(p4); - ret.add(p5); - ret.add(p6); - ret.add(p7); - ret.add(p8); - ret.add(p9); - ret.add(p10); - ret.add(p11); - ret.add(p12); - - // Rotate the geometry - ret.rotate(rotation, new paper.Point(pos[0], pos[1])); - - ret.closed = true; - ret.fillColor = color; - return ret; - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - if (key === null) { - key = this.__renderKeys[0]; - } - const render = this.render2D(params, key); - render.fillColor!.alpha = 0.5; - return render; - } -} diff --git a/src/app/library/dropletGeneratorFlowFocus.ts b/src/app/library/dropletGeneratorFlowFocus.ts deleted file mode 100755 index e8b6d7ae..00000000 --- a/src/app/library/dropletGeneratorFlowFocus.ts +++ /dev/null @@ -1,211 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class DropletGeneratorFlowFocus extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - oilChannelWidth: "Float", - waterChannelWidth: "Float", - length: "Float", - radius: "Float", - angle: "Float", - height: "Float", - rotation: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - oilChannelWidth: 0.4 * 1000, - waterChannelWidth: 0.2 * 1000, - length: 3 * 1000, - radius: 500, - angle: 45, - height: 250, - rotation: 0 - }; - - this.__units = { - componentSpacing: "μm", - oilChannelWidth: "μm", - height: "μm", - waterChannelWidth: "μm", - radius: "μm", - length: "μm", - rotation: "°", - angle: "°" - }; - - this.__minimum = { - componentSpacing: 0, - oilChannelWidth: 1, - waterChannelWidth: 1, - length: 1, - radius: 1, - angle: 1, - rotation: 0 - }; - - this.__maximum = { - componentSpacing: 10000, - oilChannelWidth: 2000, - waterChannelWidth: 2000, - length: 20000, - angle: 360, - height: 1200, - radius: 2000, - rotation: 360 - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - oilChannelWidth: "oilChannelWidth", - waterChannelWidth: "waterChannelWidth", - length: "length", - angle: "angle", - height: "height", - rotation: "rotation", - radius: "radius" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - oilChannelWidth: "oilChannelWidth", - waterChannelWidth: "waterChannelWidth", - length: "length", - angle: "angle", - height: "height", - rotation: "rotation", - radius: "radius" - }; - - this.__placementTool = "componentPositionTool"; - - this.__toolParams = { - position: "position" - }; - - this.__renderKeys = ["FLOW"]; - - this.__mint = "DROPLET GENERATOR FLOW FOCUS"; - - this.__zOffsetKeys = { - FLOW: "height" - }; - - this.__substrateOffset = { - FLOW: "0" - }; - } - - getPorts(params: { [k: string]: any }) { - const ports = []; - - ports.push(new ComponentPort(0, 0, "1", LogicalLayerType.FLOW)); - - // Out - return ports; - } - - render2D(params: { [k: string]: any }, key: string) { - const pos = params.position; - const x = pos[0]; - const y = pos[1]; - const color = params.color; - const oilChannelWidth = params.oilChannelWidth; - const waterChannelWidth = params.waterChannelWidth; - const length = params.length; - const angle = params.angle; - const radius = params.radius; - const rotation = params.rotation; - - const ret = new paper.CompoundPath(""); - - // middle path - let topLeft = new paper.Point(x - length / 3 - 2 * length, y - waterChannelWidth / 2); - let bottomRight = new paper.Point(x, y + waterChannelWidth / 2); - - ret.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - let circ = new paper.Path.Circle(new paper.Point(x - length / 3 - 2 * length, y), radius); - - ret.addChild(circ); - // top tilt path - const Hlength = length / Math.cos((angle * Math.PI) / 180); - - topLeft = new paper.Point(x - length / 3 - Hlength, y - oilChannelWidth / 2); - bottomRight = new paper.Point(x - length / 3, y + oilChannelWidth / 2); - - let tiltBlock = new paper.Path.Rectangle(topLeft, bottomRight); - tiltBlock.rotate(angle, new paper.Point(x - length / 3, y)); - - ret.addChild(tiltBlock); - - // bottom tilt path - tiltBlock = new paper.Path.Rectangle(topLeft, bottomRight); - tiltBlock.rotate(-angle, new paper.Point(x - length / 3, y)); - - ret.addChild(tiltBlock); - - // top part - const disFromMid = Hlength * Math.sin((angle * Math.PI) / 180); - const angleS = 90 - angle; - const seamCover = (oilChannelWidth / 2) * Math.tan((angleS * Math.PI) / 180); - - topLeft = new paper.Point(x - length / 3 - length - oilChannelWidth / 2, y - disFromMid - (2 * length) / 3 + seamCover); - bottomRight = new paper.Point(x - length / 3 - length + oilChannelWidth / 2, y - disFromMid + seamCover); - - ret.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x - length / 3 - 2 * length, y - disFromMid - (2 * length) / 3 + seamCover); - bottomRight = new paper.Point(x - length / 3 - length - oilChannelWidth / 2, y - disFromMid - (2 * length) / 3 + oilChannelWidth + seamCover); - - ret.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - circ = new paper.Path.Circle(new paper.Point(x - length / 3 - 2 * length, y - disFromMid - (2 * length) / 3 + seamCover + oilChannelWidth / 2), radius); - - ret.addChild(circ); - - // bottom part - topLeft = new paper.Point(x - length / 3 - length - oilChannelWidth / 2, y + disFromMid + (2 * length) / 3 - seamCover); - bottomRight = new paper.Point(x - length / 3 - length + oilChannelWidth / 2, y + disFromMid - seamCover); - - ret.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x - length / 3 - 2 * length, y + disFromMid + (2 * length) / 3 - seamCover); - bottomRight = new paper.Point(x - length / 3 - length - oilChannelWidth / 2, y + disFromMid + (2 * length) / 3 - oilChannelWidth - seamCover); - - ret.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - circ = new paper.Path.Circle(new paper.Point(x - length / 3 - 2 * length, y + disFromMid + (2 * length) / 3 - seamCover - oilChannelWidth / 2), radius); - - ret.addChild(circ); - - // Rotate the geometry - ret.rotate(rotation, new paper.Point(pos[0], pos[1])); - - ret.closed = true; - ret.fillColor = color; - return ret; - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - if (key === null) { - key = this.__renderKeys[0]; - } - const render = this.render2D(params, key); - render.fillColor!.alpha = 0.5; - return render; - } -} diff --git a/src/app/library/dropletGeneratorT.ts b/src/app/library/dropletGeneratorT.ts deleted file mode 100755 index d72ca6bd..00000000 --- a/src/app/library/dropletGeneratorT.ts +++ /dev/null @@ -1,164 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class DropletGeneratorT extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - oilChannelWidth: "Float", - waterChannelWidth: "Float", - length: "Float", - radius: "Float", - // angle: "Float", - height: "Float", - rotation: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - oilChannelWidth: 0.6 * 1000, - waterChannelWidth: 0.3 * 1000, - length: 5 * 1000, - radius: 500, - height: 250, - rotation: 0 - }; - - this.__units = { - componentSpacing: "μm", - oilChannelWidth: "μm", - height: "μm", - waterChannelWidth: "μm", - radius: "μm", - rotation: "°", - length: "μm" - }; - - this.__minimum = { - componentSpacing: 0, - oilChannelWidth: 1, - waterChannelWidth: 1, - radius: 1, - rotation: 0, - length: 0 * 1000 - }; - - this.__maximum = { - componentSpacing: 10000, - oilChannelWidth: 2000, - waterChannelWidth: 2000, - height: 1200, - radius: 2000, - rotation: 360, - length: 8 * 1000 - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - oilChannelWidth: "oilChannelWidth", - waterChannelWidth: "waterChannelWidth", - height: "height", - rotation: "rotation", - radius: "radius", - length: "length" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - oilChannelWidth: "oilChannelWidth", - waterChannelWidth: "waterChannelWidth", - height: "height", - rotation: "rotation", - radius: "radius", - length: "length" - }; - - this.__placementTool = "componentPositionTool"; - - this.__toolParams = { - position: "position" - }; - - this.__renderKeys = ["FLOW"]; - - this.__mint = "DROPLET GENERATOR T"; - - this.__zOffsetKeys = { - FLOW: "height" - }; - - this.__substrateOffset = { - FLOW: "0" - }; - } - - getPorts(params: { [k: string]: any }) { - const length = params.length; - - const ports = []; - - ports.push(new ComponentPort(length / 2, 0, "1", LogicalLayerType.FLOW)); - - // Out - return ports; - } - - render2D(params: { [k: string]: any }, key: string) { - const pos = params.position; - const x = pos[0]; - const y = pos[1]; - const color = params.color; - const oilChannelWidth = params.oilChannelWidth; - const waterChannelWidth = params.waterChannelWidth; - const radius = params.radius; - const rotation = params.rotation; - const length = params.length; - - const ret = new paper.CompoundPath(""); - - let topLeft = new paper.Point(x - length / 2, y - oilChannelWidth / 2); - let bottomRight = new paper.Point(x + length / 2, y + oilChannelWidth / 2); - - ret.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - let circ = new paper.Path.Circle(new paper.Point(x - length / 2, y), radius); - - ret.addChild(circ); - - topLeft = new paper.Point(x - waterChannelWidth / 2, y); - bottomRight = new paper.Point(x + waterChannelWidth / 2, y + length / 2); - - ret.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - circ = new paper.Path.Circle(new paper.Point(x, y + length / 2), radius); - - ret.addChild(circ); - - // Rotate the geometry - ret.closed = true; - ret.rotate(rotation, new paper.Point(x, y)); - ret.fillColor = color; - - return ret; - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - if (key === null) { - key = this.__renderKeys[0]; - } - const render = this.render2D(params, key); - render.fillColor!.alpha = 0.5; - return render; - } -} diff --git a/src/app/library/dropletMerger.ts b/src/app/library/dropletMerger.ts deleted file mode 100644 index 46ac1a98..00000000 --- a/src/app/library/dropletMerger.ts +++ /dev/null @@ -1,164 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class DropletMerger extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - inputWidth1: "Float", - inputWidth2: "Float", - outputWidth: "Float", - stabilizationLength: "Float", - rotation: "Float", - height: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - inputWidth1: 400, - inputWidth2: 400, - outputWidth: 400, - stabilizationLength: 5000, - rotation: 0, - height: 250 - }; - - this.__units = { - componentSpacing: "μm", - inputWidth1: "μm", - inputWidth2: "μm", - outputWidth: "μm", - stabilizationLength: "μm", - rotation: "°", - height: "μm" - }; - - this.__minimum = { - componentSpacing: 0, - inputWidth1: 1, - inputWidth2: 1, - outputWidth: 1, - stabilizationLength: 10, - rotation: 0, - height: 10 - }; - - this.__maximum = { - componentSpacing: 10000, - inputWidth1: 10000, - inputWidth2: 10000, - outputWidth: 10000, - stabilizationLength: 500000, - rotation: 360, - height: 10000 - }; - - this.__placementTool = "componentPositionTool"; - - this.__toolParams = { - cursorPosition: "position" - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - inputWidth1: "inputWidth1", - inputWidth2: "inputWidth2", - outputWidth: "outputWidth", - stabilizationLength: "stabilizationLength", - rotation: "rotation;", - height: "height" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - inputWidth1: "inputWidth1", - inputWidth2: "inputWidth2", - outputWidth: "outputWidth", - stabilizationLength: "stabilizationLength", - rotation: "rotation;" - }; - - this.__renderKeys = ["FLOW"]; - - this.__mint = "DROPLET MERGER"; - - this.__zOffsetKeys = { - FLOW: "height" - }; - - this.__substrateOffset = { - FLOW: "0" - }; - } - - getPorts(params: { [k: string]: any }) { - const channelWidth = params.channelWidth; - const bendLength = params.bendLength; - const bendSpacing = params.bendSpacing; - const rotation = params.rotation; - const numberOfBends = params.numberOfBends; - - const ports = []; - - ports.push(new ComponentPort(bendLength / 2 + channelWidth, 0, "1", LogicalLayerType.FLOW)); - - ports.push(new ComponentPort(bendLength / 2 + channelWidth, (2 * numberOfBends + 1) * channelWidth + 2 * numberOfBends * bendSpacing, "2", LogicalLayerType.FLOW)); - - return ports; - } - - render2D(params: { [k: string]: any }, key: string): paper.CompoundPath { - const channelWidth = params.channelWidth; - const bendLength = params.bendLength; - const bendSpacing = params.bendSpacing; - const rotation = params.rotation; - const numBends = params.numberOfBends; - const x = params.position[0]; - const y = params.position[1]; - const color = params.color; - const segHalf = bendLength / 2 + channelWidth; - const segLength = bendLength + 2 * channelWidth; - const segBend = bendSpacing + 2 * channelWidth; - const vRepeat = 2 * bendSpacing + 2 * channelWidth; - const vOffset = bendSpacing + channelWidth; - const hOffset = bendLength / 2 + channelWidth / 2; - const serp = new paper.CompoundPath(""); - // draw first segment - serp.addChild(new paper.Path.Rectangle(new paper.Rectangle(x, y, segHalf + channelWidth / 2, channelWidth))); - for (let i = 0; i < numBends; i++) { - serp.addChild(new paper.Path.Rectangle(new paper.Rectangle(x, y + vRepeat * i, channelWidth, segBend))); - serp.addChild(new paper.Path.Rectangle(new paper.Rectangle(x, y + vOffset + vRepeat * i, segLength, channelWidth))); - serp.addChild(new paper.Path.Rectangle(new paper.Rectangle(x + channelWidth + bendLength, y + vOffset + vRepeat * i, channelWidth, segBend))); - if (i === numBends - 1) { - // draw half segment to close - serp.addChild(new paper.Path.Rectangle(new paper.Rectangle(x + hOffset, y + vRepeat * (i + 1), segHalf, channelWidth))); - } else { - // draw full segment - serp.addChild(new paper.Path.Rectangle(new paper.Rectangle(x, y + vRepeat * (i + 1), segLength, channelWidth))); - } - } - - serp.fillColor = color; - return (serp.rotate(rotation, new paper.Point(x, y)) as unknown) as paper.CompoundPath; - } - - render2DTarget(key: string | null, params: { [k: string]: any }): paper.CompoundPath { - if (key === null) { - key = this.__renderKeys[0]; - } - const serp = this.render2D(params, key); - serp.fillColor!.alpha = 0.5; - return serp; - } -} diff --git a/src/app/library/filter.ts b/src/app/library/filter.ts deleted file mode 100644 index 29a26369..00000000 --- a/src/app/library/filter.ts +++ /dev/null @@ -1,294 +0,0 @@ -import Template from "./template"; -import paper, { Path } from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class Filter extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - rotation: "Float", - height: "Float", - pillarDiameter: "Float", - filterWidth: "Float", - barrierWidth: "Float", - filterLength: "Float", - filterNumber: "Float", - levelNumber: "Float", - inletWidth: "Float", - inletLength: "Float", - outletWidth: "Float", - outletLength: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - rotation: 0, - height: 250, - pillarDiameter: 2 * 1000, - filterWidth: 1 * 1000, - barrierWidth: 1 * 1000, - filterLength: 3 * 1000, - filterNumber: 5, - levelNumber: 2, - inletWidth: 1 * 1000, - inletLength: 3 * 1000, - outletWidth: 1 * 1000, - outletLength: 3 * 1000 - }; - - this.__units = { - componentSpacing: "μm", - rotation: "°", - height: "μm", - pillarDiameter: "μm", - filterWidth: "μm", - barrierWidth: "μm", - filterLength: "μm", - filterNumber: "", - levelNumber: "", - inletWidth: "μm", - inletLength: "μm", - outletWidth: "μm", - outletLength: "μm" - }; - - this.__minimum = { - componentSpacing: 0, - rotation: 0, - height: 10, - pillarDiameter: 1 * 1000, - filterWidth: 0.5 * 1000, - barrierWidth: 0.5 * 1000, - filterLength: 2 * 1000, - filterNumber: 2, - levelNumber: 1, - inletWidth: 0.5 * 1000, - inletLength: 1 * 1000, - outletWidth: 0.5 * 1000, - outletLength: 1 * 1000 - }; - - this.__maximum = { - componentSpacing: 10000, - rotation: 360, - height: 1200, - pillarDiameter: 4 * 1000, - filterWidth: 4 * 1000, - barrierWidth: 6 * 1000, - filterLength: 9 * 1000, - filterNumber: 5, - levelNumber: 10, - inletWidth: 4 * 1000, - inletLength: 8 * 1000, - outletWidth: 4 * 1000, - outletLength: 8 * 1000 - }; - - this.__placementTool = "componentPositionTool"; - - this.__toolParams = { - cursorPosition: "position" - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - rotation: "rotation", - pillarDiameter: "pillarDiameter", - filterWidth: "filterWidth", - barrierWidth: "barrierWidth", - filterLength: "filterLength", - filterNumber: "filterNumber", - levelNumber: "levelNumber", - inletWidth: "inletWidth", - inletLength: "inletLength", - outletWidth: "outletWidth", - outletLength: "outletLength" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - rotation: "rotation", - pillarDiameter: "pillarDiameter", - filterWidth: "filterWidth", - barrierWidth: "barrierWidth", - filterLength: "filterLength", - filterNumber: "filterNumber", - levelNumber: "levelNumber", - inletWidth: "inletWidth", - inletLength: "inletLength", - outletWidth: "outletWidth", - outletLength: "outletLength" - }; - - this.__renderKeys = ["FLOW"]; - - this.__mint = "FILTER"; - - this.__zOffsetKeys = { - FLOW: "height" - }; - - this.__substrateOffset = { - FLOW: "0" - }; - } - - getPorts(params: { [k: string]: any }) { - const inletLength = params.inletLength; - const filterLength = params.filterLength; - const outletLength = params.outletLength; - const levelNumber = params.levelNumber; - const pillarDiameter = params.pillarDiameter; - - const ports = []; - - ports.push(new ComponentPort(0, 0, "1", LogicalLayerType.FLOW)); - - ports.push(new ComponentPort(inletLength + 5 * pillarDiameter + 1.3 * levelNumber * filterLength + outletLength, 0, "2", LogicalLayerType.FLOW)); - - return ports; - } - - render2D(params: { [k: string]: any }, key: string) { - const rotation = params.rotation; - const x = params.position[0]; - const y = params.position[1]; - const color = params.color; - const pillarDiameter = params.pillarDiameter; - const filterWidth = params.filterWidth; - const barrierWidth = params.barrierWidth; - const filterLength = params.filterLength; - const filterNumber = params.filterNumber; - const levelNumber = params.levelNumber; - const inletWidth = params.inletWidth; - const inletLength = params.inletLength; - const outletWidth = params.outletWidth; - const outletLength = params.outletLength; - - const serp = new paper.CompoundPath(""); - - const bodyWidth = filterNumber * filterWidth + (filterNumber - 1) * barrierWidth; - - // inlet - let topLeft = new paper.Point(x, y - inletWidth / 2); - let bottomRight = new paper.Point(x + inletLength, y + inletWidth / 2); - - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // left pillar - topLeft = new paper.Point(x + inletLength, y - inletWidth / 2); - let topRight = new paper.Point(x + inletLength + 2.5 * pillarDiameter, y - bodyWidth / 2); - let bottomLeft = new paper.Point(x + inletLength, y + inletWidth / 2); - bottomRight = new paper.Point(x + inletLength + 2.5 * pillarDiameter, y + bodyWidth / 2); - - let pillarPath: paper.Path | paper.PathItem = new paper.Path(); - (pillarPath as paper.Path).add(topLeft); - (pillarPath as paper.Path).add(topRight); - (pillarPath as paper.Path).add(bottomRight); - (pillarPath as paper.Path).add(bottomLeft); - - let circ = new paper.Path.Circle(new paper.Point(x + inletLength + 1.5 * pillarDiameter, y), pillarDiameter / 2); - - pillarPath = pillarPath.subtract(circ); - - serp.addChild(pillarPath); - - // body tube - let startBody = inletLength + 2.5 * pillarDiameter; - const extraSpace = 0.3 * filterLength; - - for (let i = 0; i < levelNumber; i++) { - topLeft = new paper.Point(x + startBody, y - bodyWidth / 2); - bottomRight = new paper.Point(x + startBody + filterLength + extraSpace, y + bodyWidth / 2); - - let rec: paper.PathItem | paper.Rectangle = new paper.Path.Rectangle(topLeft, bottomRight); - - if (i % 2 === 0) { - const division = (bodyWidth - (filterNumber - 1) * barrierWidth) / filterNumber; - let heightAccum = division; - - for (let j = 0; j < filterNumber - 1; j++) { - topLeft = new paper.Point(x + startBody + extraSpace / 2, y - bodyWidth / 2 + heightAccum); - heightAccum += barrierWidth; - bottomRight = new paper.Point(x + startBody + filterLength, y - bodyWidth / 2 + heightAccum); - - const cutrec = new paper.Path.Rectangle(topLeft, bottomRight); - - rec = rec.subtract(cutrec); - - heightAccum += division; - } - } else { - const division = (bodyWidth - (filterNumber - 2) * barrierWidth) / (filterNumber - 1); - let heightAccum = division; - - for (let j = 0; j < filterNumber - 2; j++) { - topLeft = new paper.Point(x + startBody + extraSpace / 2, y - bodyWidth / 2 + heightAccum); - heightAccum += barrierWidth; - bottomRight = new paper.Point(x + startBody + filterLength, y - bodyWidth / 2 + heightAccum); - - const cutrec = new paper.Path.Rectangle(topLeft, bottomRight); - - rec = rec.subtract(cutrec); - - heightAccum += division; - } - } - - serp.addChild(rec); - - startBody += filterLength + extraSpace; - } - - // right pillar - topLeft = new paper.Point(x + startBody, y - bodyWidth / 2); - topRight = new paper.Point(x + startBody + 2.5 * pillarDiameter, y - outletWidth / 2); - bottomRight = new paper.Point(x + startBody + 2.5 * pillarDiameter, y + outletWidth / 2); - bottomLeft = new paper.Point(x + startBody, y + bodyWidth / 2); - - pillarPath = new paper.Path(); - - (pillarPath as paper.Path).add(topLeft); - (pillarPath as paper.Path).add(topRight); - (pillarPath as paper.Path).add(bottomRight); - (pillarPath as paper.Path).add(bottomLeft); - - startBody += 2.5 * pillarDiameter; - - circ = new paper.Path.Circle(new paper.Point(x + startBody - 1.5 * pillarDiameter, y), pillarDiameter / 2); - - pillarPath = pillarPath.subtract(circ); - - serp.addChild(pillarPath); - - // outlet - topLeft = new paper.Point(x + startBody, y - outletWidth / 2); - bottomRight = new paper.Point(x + startBody + outletLength, y + outletWidth / 2); - - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - serp.rotate(rotation, new paper.Point(x, y)); - - serp.fillColor = color; - return serp; - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - if (key === null) { - key = this.__renderKeys[0]; - } - const serp = this.render2D(params, key); - serp.fillColor!.alpha = 0.5; - return serp; - } -} diff --git a/src/app/library/gelchannel.ts b/src/app/library/gelchannel.ts deleted file mode 100644 index 46503202..00000000 --- a/src/app/library/gelchannel.ts +++ /dev/null @@ -1,201 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class Gelchannel extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - sideWidth: "Float", - mainWidth: "Float", - rotation: "Float", - length: "Float", - height: "Float", - sideheight: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - sideWidth: 200, - mainWidth: 500, - rotation: 0, - length: 3000, - height: 250, - sideheight: 50 - }; - - this.__units = { - componentSpacing: "μm", - sideWidth: "μm", - mainWidth: "μm", - rotation: "°", - length: "μm", - height: "μm", - sideheight: "μm" - }; - - this.__minimum = { - componentSpacing: 0, - sideWidth: 20, - mainWidth: 10, - length: 1000, - height: 10, - sideheight: 10, - rotation: 0 - }; - - this.__maximum = { - componentSpacing: 10000, - sideWidth: 500, - mainWidth: 500, - length: 100 * 1000, - height: 1200, - sideheight: 1200, - rotation: 360 - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - rotation: "rotation", - length: "length", - sideWidth: "sideWidth", - mainWidth: "mainWidth", - height: "height", - sideheight: "sideheight" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - rotation: "rotation", - length: "length", - sideWidth: "sideWidth", - mainWidth: "mainWidth", - height: "height", - sideheight: "sideheight" - }; - - this.__placementTool = "CellPositionTool"; - - this.__toolParams = { - position: "position" - }; - - this.__renderKeys = ["FLOW", "CELL"]; - - this.__mint = "GEL CHANNEL"; - - this.__zOffsetKeys = { - FLOW: "height", - CELL: "sideHeight" - }; - - this.__substrateOffset = { - FLOW: "0", - CELL: "0" - }; - } - - getPorts(params: { [k: string]: any }) { - const ports = []; - const sideWidth = params.sideWidth; - const numChambers = 2; - const length = params.length; - const mainWidth = params.mainWidth; - - ports.push(new ComponentPort(0, sideWidth + mainWidth / 2, "1", LogicalLayerType.FLOW)); - ports.push(new ComponentPort((numChambers / 2) * (length + 60) + 60, sideWidth + mainWidth / 2, "2", LogicalLayerType.FLOW)); - - return ports; - } - - render2D(params: { [k: string]: any }, key: string) { - if (key === "FLOW") { - return this.__drawFlow(params); - } else if (key === "CELL") { - return this.__drawCell(params); - } - - throw new Error("Unknown key: " + key); - - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - const traps = this.__drawFlow(params); - traps.addChild(this.__drawCell(params)); - traps.fillColor!.alpha = 0.5; - return traps; - } - - __drawFlow(params: { [k: string]: any }) { - const rotation = params.rotation; - const position = params.position; - const sideWidth = params.sideWidth; - const numChambers = 2; - const length = params.length; - const mainWidth = params.mainWidth; - - console.log(rotation, position, sideWidth, numChambers, length, mainWidth, 60); - const color = params.color; - const x = position[0]; - const y = position[1]; - const chamberList = new paper.CompoundPath(""); - chamberList.fillColor = color; - let traps; - let channels; - - const startPoint = new paper.Point(x, y + sideWidth); - channels = new paper.Path.Rectangle({ - point: startPoint, - size: [(numChambers / 2) * (length + 60) + 60, mainWidth], - fillColor: color, - strokeWidth: 0 - }); - chamberList.addChild(channels); - - traps = new paper.CompoundPath(chamberList); - traps.fillColor = color; - const center = new paper.Point(position[0], position[1]); - traps.rotate(rotation, center); - return traps; - } - - __drawCell(params: { [k: string]: any }) { - const rotation = params.rotation; - const position = params.position; - const sideWidth = params.sideWidth; - const numChambers = 2; - const length = params.length; - const mainWidth = params.mainWidth; - const color = params.color; - const x = position[0]; - const y = position[1]; - const chamberList = new paper.CompoundPath(""); - let rec; - - for (let i = 0; i < numChambers / 2; i++) { - const startPoint = new paper.Point(x + i * (length + 60) + 60, y); - rec = new paper.Path.Rectangle({ - size: [length, 2 * sideWidth + mainWidth], - point: startPoint, - fillColor: color, - strokeWidth: 0 - }); - chamberList.addChild(rec); - } - - chamberList.fillColor = color; - const center = new paper.Point(x, y); - chamberList.rotate(rotation, center); - return chamberList; - } -} diff --git a/src/app/library/geometricElements/featureTemplate.ts b/src/app/library/geometricElements/featureTemplate.ts deleted file mode 100755 index 28ab6548..00000000 --- a/src/app/library/geometricElements/featureTemplate.ts +++ /dev/null @@ -1,100 +0,0 @@ - -import ComponentPort from "../../core/componentPort"; -import { GeometricOperationType, ToolPaperObject } from "../../core/init"; -import paper from "paper"; -//import { ManufacturingInfo } from "../manufacturing/ManufacturingInfo"; -import { LogicalLayerType } from "../../core/init"; -import {PRIMITIVES_SERVER} from "../../../componentAPI"; - -export default class FeatureTemplate { - - protected _macro: string = "FeatureTemplate"; - protected _geometricOperation: GeometricOperationType = GeometricOperationType.UNION; - protected __unique: { [key: string]: string } | null = null; - protected __heritable: { [key: string]: string } | null = null; - protected __defaults: { [key: string]: number } | null = null; - protected __minimum: { [key: string]: number } | null = null; - protected __maximum: { [key: string]: number } | null = null; - protected __units: { [key: string]: string } | null = null; - protected __toolParams: { [key: string]: string } | null = null; // { position: "position" }; - protected __featureParams: { [key: string]: string } | null = null; - protected __targetParams: { [key: string]: string } | null = null; - protected __zOffsetKeys: { [key: string]: string } | null = null; - protected __substrateOffset: { [key: string]: string } | null = null; - - - /** - *Creates an instance of Template. - * @memberof Template - */ - constructor() { - this.__setupDefinitions(); - this.__checkDefinitions(); - } - - __setupDefinitions(): void { - //Throw an error if this function is not implemented - throw new Error("Method not implemented."); - } - - __checkDefinitions(): void { - //Check that all the definitions are set - if (this._macro === null) { - throw new Error("Macro not defined: " + this._macro); - } - if (this.__unique === null) { - throw new Error("Unique parameters not defined: " + this._macro); - } - if (this.__heritable === null) { - throw new Error("Heritable parameters not defined: " + this._macro); - } - if (this.__defaults === null) { - throw new Error("Default parameters not defined: " + this._macro); - } - if (this.__minimum === null) { - throw new Error("Minimum parameters not defined: " + this._macro); - } - if (this.__maximum === null) { - throw new Error("Maximum parameters not defined: " + this._macro); - } - if (this.__units === null) { - throw new Error("Units not defined: " + this._macro); - } - if (this.__toolParams === null) { - throw new Error("Tool parameters not defined: " + this._macro); - } - if (this.__featureParams === null) { - throw new Error("Feature parameters not defined: " + this._macro); - } - if (this.__targetParams === null) { - throw new Error("Target parameters not defined: " + this._macro); - } - } - - /** - * Get the Macro parameters for the feature - * - * @type {GeometricOperationType} - * @memberof FeatureTemplate - */ - get geometricOperation(): GeometricOperationType { - return this._geometricOperation; - } - - /** - * Get the Macro parameters for the feature - * - * @type {string} - * @memberof FeatureTemplate - */ - get macro(): string { - return this._macro; - } - - render2d(params: { [key: string]: any }): ToolPaperObject { - //Throw an error if this function is not implemented - throw new Error("Method not implemented."); - } - -} - diff --git a/src/app/library/geometricElements/normallyClosedValveCrecents.ts b/src/app/library/geometricElements/normallyClosedValveCrecents.ts deleted file mode 100644 index cb1bfbb6..00000000 --- a/src/app/library/geometricElements/normallyClosedValveCrecents.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { GeometricOperationType } from "@/app/core/init"; -import FeatureTemplate from "./featureTemplate"; - -export default class NormallyClosedValveCrescents extends FeatureTemplate { - constructor() { - super(); - } - - __setupDefinitions(): void { - this._macro = "VALVE3D FLOW"; - - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - rotation: "Float", - valveRadius: "Float", - height: "Float", - gap: "Float", - width: "Float", - length: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - rotation: 0, - valveRadius: 1.2 * 1000, - height: 250, - gap: 0.6 * 1000, - width: 2.4 * 1000, - length: 2.4 * 1000 - }; - - this.__units = { - componentSpacing: "μm", - valveRadius: "μm", - height: "μm", - gap: "μm", - width: "μm", - length: "μm", - rotation: "°" - }; - - this.__minimum = { - componentSpacing: 0, - valveRadius: 0.1 * 100, - height: 0.1 * 100, - gap: 0.5 * 10, - rotation: 0, - width: 10, - length: 10 - }; - - this.__maximum = { - componentSpacing: 10000, - valveRadius: 0.3 * 10000, - height: 1.2 * 1000, - gap: 0.1 * 10000, - rotation: 180, - width: 3 * 1000, - length: 3 * 1000 - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - rotation: "rotation", - radius1: "valveRadius", - radius2: "valveRadius", - valveRadius: "valveRadius", - gap: "gap" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - position: "position", - rotation: "rotation", - radius1: "valveRadius", - radius2: "valveRadius", - valveRadius: "valveRadius", - gap: "gap" - }; - - - this.__toolParams = { - position: "position" - }; - - this._geometricOperation = GeometricOperationType.UNION; - // TODO: Setup the manufacuring info for this feature - } - -} \ No newline at end of file diff --git a/src/app/library/geometricElements/normallyClosedValveGap.ts b/src/app/library/geometricElements/normallyClosedValveGap.ts deleted file mode 100644 index ac40cddd..00000000 --- a/src/app/library/geometricElements/normallyClosedValveGap.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { GeometricOperationType } from "@/app/core/init"; -import FeatureTemplate from "./featureTemplate"; - -export default class NormallyClosedValveModificationsGap extends FeatureTemplate { - constructor() { - super(); - } - - __setupDefinitions(): void { - this._macro = "VALVE3D GAP"; - - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - rotation: "Float", - valveRadius: "Float", - height: "Float", - gap: "Float", - width: "Float", - length: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - rotation: 0, - valveRadius: 1.2 * 1000, - height: 250, - gap: 0.6 * 1000, - width: 2.4 * 1000, - length: 2.4 * 1000 - }; - - this.__units = { - componentSpacing: "μm", - valveRadius: "μm", - height: "μm", - gap: "μm", - width: "μm", - length: "μm", - rotation: "°" - }; - - this.__minimum = { - componentSpacing: 0, - valveRadius: 0.1 * 100, - height: 0.1 * 100, - gap: 0.5 * 10, - rotation: 0, - width: 10, - length: 10 - - }; - - this.__maximum = { - componentSpacing: 10000, - valveRadius: 0.3 * 10000, - height: 1.2 * 1000, - gap: 0.1 * 10000, - rotation: 180, - width: 3 * 1000, - length: 3 * 1000 - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - rotation: "rotation", - radius1: "valveRadius", - radius2: "valveRadius", - valveRadius: "valveRadius", - gap: "gap" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - position: "position", - rotation: "rotation", - radius1: "valveRadius", - radius2: "valveRadius", - valveRadius: "valveRadius", - gap: "gap" - }; - - this.__toolParams = { - position: "position" - }; - - this._geometricOperation = GeometricOperationType.DIFFERENCE; - // TODO: Setup the manufacuring info for this feature - } - -} \ No newline at end of file diff --git a/src/app/library/gradientGenerator.ts b/src/app/library/gradientGenerator.ts deleted file mode 100755 index 5a9e1f9c..00000000 --- a/src/app/library/gradientGenerator.ts +++ /dev/null @@ -1,289 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class GradientGenerator extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - bendSpacing: "Float", - numberOfBends: "Float", - channelWidth: "Float", - bendLength: "Float", - in: "Float", - out: "Float", - spacing: "Float", - height: "Float", - rotation: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - channelWidth: 0.8 * 1000, - bendSpacing: 1.23 * 1000, - numberOfBends: 1, - bendLength: 2.46 * 1000, - in: 1, - out: 3, - spacing: 10000, - height: 250, - rotation: 0 - }; - - this.__units = { - componentSpacing: "μm", - bendSpacing: "μm", - numberOfBends: "", - channelWidth: "μm", - bendLength: "μm", - in: "", - out: "", - spacing: "μm", - height: "μm", - rotation: "°" - }; - - this.__minimum = { - componentSpacing: 0, - channelWidth: 10, - bendSpacing: 10, - numberOfBends: 1, - bendLength: 10, - in: 1, - out: 3, - spacing: 10, - height: 10, - rotation: 0 - }; - - this.__maximum = { - componentSpacing: 10000, - channelWidth: 2000, - bendSpacing: 6000, - numberOfBends: 20, - bendLength: 12 * 1000, - in: 30, - out: 90, - spacing: 90000, - height: 1200, - rotation: 360 - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - channelWidth: "channelWidth", - bendSpacing: "bendSpacing", - numberOfBends: "numberOfBends", - rotation: "rotation", - bendLength: "bendLength", - in: "in", - out: "out", - spacing: "spacing" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - channelWidth: "channelWidth", - bendSpacing: "bendSpacing", - numberOfBends: "numberOfBends", - rotation: "rotation", - bendLength: "bendLength", - in: "in", - out: "out", - spacing: "spacing" - }; - - this.__placementTool = "componentPositionTool"; - - this.__toolParams = { - position: "position" - }; - - this.__renderKeys = ["FLOW"]; - - this.__mint = "GRADIENT GENERATOR"; - - this.__zOffsetKeys = { - FLOW: "height" - }; - - this.__substrateOffset = { - FLOW: "0" - }; - } - - getPorts(params: { [k: string]: any }) { - const bendSpacing = params.bendSpacing; - const numBends = params.numberOfBends; - const channelWidth = params.channelWidth; - const invalue = params.in; - const outvalue = params.out; - const spacing = params.spacing; // Center to Center - - const ports = []; - - const maxstagewidth = (outvalue - 1) * spacing; - const posx = maxstagewidth / 2; - - const stagelength = channelWidth * (2 * numBends + 1) + (2 * numBends + 2) * bendSpacing + channelWidth; - - const segBend = bendSpacing + 2 * channelWidth; - - const fullLength = (outvalue - 1) * (4 * segBend - 3.5 * channelWidth) + stagelength; - - let stagevalue = invalue; - let totalstagewidth = (stagevalue - 1) * spacing; - - let xref = -totalstagewidth / 2; - let yref = stagelength * (stagevalue - invalue); - - const vRepeat = 2 * bendSpacing + 2 * channelWidth; - - for (let i = 0; i < invalue; i++) { - // Generate the ports for each of the inputs - const x = xref + spacing * i + channelWidth / 2; - ports.push(new ComponentPort(x, 0, (i + 1).toString(), LogicalLayerType.FLOW)); - } - - stagevalue = outvalue; - totalstagewidth = (stagevalue - 1) * spacing; - - xref = -totalstagewidth / 2; - yref = stagelength * (stagevalue - invalue + 1); - - for (let i = 0; i < outvalue; i++) { - // Generate the ports for each of the outputs - const x = xref + spacing * i + channelWidth / 2; - ports.push(new ComponentPort(x, yref + channelWidth, (invalue + 1 + i).toString(), LogicalLayerType.FLOW)); - } - - return ports; - } - - render2D(params: { [k: string]: any }, key: string) { - const position = params.position; - const bendSpacing = params.bendSpacing; - const numBends = params.numberOfBends; - const channelWidth = params.channelWidth; - const bendLength = params.bendLength; - const rotation = params.rotation; - const invalue = params.in; - const outvalue = params.out; - const spacing = params.spacing; // Center to Center - const color = params.color; - - const posx = position[0]; - const posy = position[1]; - const stagelength = channelWidth * (2 * numBends + 1) + (2 * numBends + 2) * bendSpacing + channelWidth; - const gradientgenerator = new paper.CompoundPath(""); - // insertMixer(gradientgenerator, bendSpacing, numBends, channelWidth, bendLength, posx, posy, color); - // Iterate through each of the stages - - // Draw the first stage which is just channels - const totalstagewidth = (invalue - 1) * spacing; - let xref = posx - totalstagewidth / 2; - let yref = posy; - // Draw straight channels for each of the input lines - for (let i = 0; i < invalue; i++) { - const x = xref + spacing * i; - const y = yref; - - // Insert Straight channel - gradientgenerator.addChild( - new paper.Path.Rectangle({ - point: new paper.Point(x, y), - size: [channelWidth, stagelength + channelWidth] - }) - ); - } - - for (let stagevalue = invalue + 1; stagevalue <= outvalue; stagevalue++) { - // For each stage : do the following - /* - Check if each stagevalue is odd or even - - if (not last stage) place horizontal bar connecting eveything - */ - - // Calculate the total width and start placing mixers - const totalstagewidth = (stagevalue - 1) * spacing; - - xref = posx - totalstagewidth / 2; - yref = posy + stagelength * (stagevalue - invalue); - - // Start from the left - for (let i = 0; i < stagevalue; i++) { - const x = xref + spacing * i; - - const y = yref; - // insert the mixer - this.__insertMixer(gradientgenerator as paper.Path, bendSpacing, numBends, channelWidth, bendLength, x, y, color); - } - - // Insert horizontal bar - const hbar = new paper.Path.Rectangle({ - point: new paper.Point(xref, yref), - size: [totalstagewidth, channelWidth], - fillColor: color, - strokeWidth: 0 - }); - - gradientgenerator.addChild(hbar); - } - - gradientgenerator.fillColor = color; - // console.log("testing"); - - gradientgenerator.rotate(rotation, new paper.Point(posx, posy)); - - return gradientgenerator; - } - - __insertMixer(serpentine: paper.Path, bendSpacing: number, numBends: number, channelWidth: number, bendLength: number, x: number, y: number, color: paper.Color): paper.Path { - const segHalf = bendLength / 2 + channelWidth; - const segLength = bendLength + 2 * channelWidth; - const segBend = bendSpacing + 2 * channelWidth; - const vRepeat = 2 * bendSpacing + 2 * channelWidth; - const vOffset = bendSpacing + channelWidth; - const hOffset = bendLength / 2 + channelWidth / 2; - - x -= hOffset; - // TopRectangle - serpentine.addChild(new paper.Path.Rectangle(new paper.Rectangle(x + hOffset, y, channelWidth, 2 * channelWidth + bendSpacing))); - y += channelWidth + bendSpacing; - serpentine.addChild(new paper.Path.Rectangle(new paper.Rectangle(x, y, segHalf + channelWidth / 2, channelWidth))); - for (let i = 0; i < numBends; i++) { - serpentine.addChild(new paper.Path.Rectangle(new paper.Rectangle(x, y + vRepeat * i, channelWidth, segBend))); - serpentine.addChild(new paper.Path.Rectangle(new paper.Rectangle(x, y + vOffset + vRepeat * i, segLength, channelWidth))); - serpentine.addChild(new paper.Path.Rectangle(new paper.Rectangle(x + channelWidth + bendLength, y + vOffset + vRepeat * i, channelWidth, segBend))); - if (i === numBends - 1) { - // draw half segment to close - serpentine.addChild(new paper.Path.Rectangle(new paper.Rectangle(x + hOffset, y + vRepeat * (i + 1), segHalf, channelWidth))); - } else { - // draw full segment - serpentine.addChild(new paper.Path.Rectangle(new paper.Rectangle(x, y + vRepeat * (i + 1), segLength, channelWidth))); - } - } - - // Bottom rectabvke - serpentine.addChild(new paper.Path.Rectangle(new paper.Rectangle(x + hOffset, y + vRepeat * numBends, channelWidth, 2 * channelWidth + bendSpacing))); - - return serpentine; - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - const render = this.render2D(params, (key = "FLOW")); - render.fillColor!.alpha = 0.5; - return render; - } -} diff --git a/src/app/library/incubation.ts b/src/app/library/incubation.ts deleted file mode 100644 index 7b48241d..00000000 --- a/src/app/library/incubation.ts +++ /dev/null @@ -1,157 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class Incubation extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - rotation: "Float", - channelWidth: "Float", - length: "Float", - width: "Float", - height: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - rotation: 0, - channelWidth: 0.8 * 1000, - width: 1.23 * 1000, - length: 4.92 * 1000, - height: 250 - }; - - this.__units = { - componentSpacing: "μm", - rotation: "°", - channelWidth: "μm", - length: "μm", - width: "μm", - height: "μm" - }; - - this.__minimum = { - componentSpacing: 0, - rotation: 0, - channelWidth: 10, - width: 30, - length: 120, - height: 10 - }; - - this.__maximum = { - componentSpacing: 10000, - rotation: 360, - channelWidth: 2000, - width: 6000, - length: 24 * 1000, - height: 1200 - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - rotation: "rotation", - channelWidth: "channelWidth", - length: "length", - width: "width" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - channelWidth: "channelWidth", - length: "length", - width: "width", - rotation: "rotation" - }; - - this.__placementTool = "componentPositionTool"; - - this.__toolParams = { - position: "position" - }; - - this.__renderKeys = ["FLOW"]; - - this.__mint = "INCUBATION"; - - this.__zOffsetKeys = { - FLOW: "height" - }; - - this.__substrateOffset = { - FLOW: "0" - }; - } - - getPorts(params: { [k: string]: any }) { - const length = params.length; - - const ports = []; - - ports.push(new ComponentPort(0, -length / 2, "1", LogicalLayerType.FLOW)); - - ports.push(new ComponentPort(0, length / 2, "2", LogicalLayerType.FLOW)); - - return ports; - } - - render2D(params: { [k: string]: any }, key: string) { - const position = params.position; - const px = position[0]; - const py = position[1]; - const cw = params.channelWidth; - const l = params.length; - const w = params.width; - const rotation = params.rotation; - const color = params.color; - let p0, p1, p2, p3, p4, p5; - // if (rotation === "H") { - // p0 = [px - l / 2, py - cw / 2]; - // p1 = [px - l / 2, py + cw / 2]; - // p2 = [px, py + w + cw / 2]; - // p3 = [px + l / 2, py + cw / 2]; - // p4 = [px + l / 2, py - cw / 2]; - // p5 = [px, py - cw / 2 - w]; - // } else { - p0 = [px - cw / 2, py - l / 2]; - p1 = [px + cw / 2, py - l / 2]; - p2 = [px + w + cw / 2, py]; - p3 = [px + cw / 2, py + l / 2]; - p4 = [px - cw / 2, py + l / 2]; - p5 = [px - cw / 2 - w, py]; - // } - const hex = new paper.Path(); - hex.add(new paper.Point(p0)); - hex.add(new paper.Point(p1)); - hex.add(new paper.Point(p2)); - hex.add(new paper.Point(p3)); - hex.add(new paper.Point(p4)); - hex.add(new paper.Point(p5)); - hex.closed = true; - hex.fillColor = color; - - hex.rotate(rotation, new paper.Point(px, py)); - - return hex; - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - if (key === null) { - key = this.__renderKeys[0]; - } - const render = this.render2D(params, key); - render.fillColor!.alpha = 0.5; - return render; - } -} diff --git a/src/app/library/llChamber.ts b/src/app/library/llChamber.ts deleted file mode 100644 index 3e81cfbc..00000000 --- a/src/app/library/llChamber.ts +++ /dev/null @@ -1,252 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class LLChamber extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - width: "Float", - length: "Float", - height: "Float", - rotation: "Float", - spacing: "Float", - numberOfChambers: "Integer" - }; - - this.__defaults = { - componentSpacing: 1000, - width: 400, - length: 5000, - height: 250, - spacing: 2000, - numberOfChambers: 4, - rotation: 0 - }; - - this.__units = { - componentSpacing: "μm", - width: "μm", - length: "μm", - height: "μm", - spacing: "μm", - numberOfChambers: "10", - rotation: "°" - }; - - this.__minimum = { - componentSpacing: 0, - width: 5, - length: 5, - height: 1, - spacing: 1, - numberOfChambers: 1, - rotation: 0 - }; - - this.__maximum = { - componentSpacing: 10000, - width: 50000, - length: 50000, - height: 50000, - numberOfChambers: 1000, - spacing: 50000, - rotation: 360 - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - width: "width", - length: "length", - height: "height", - numberOfChambers: "numberOfChambers", - spacing: "spacing", - rotation: "rotation" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - position: "position", - width: "width", - length: "length", - height: "height", - numberOfChambers: "numberOfChambers", - spacing: "spacing", - rotation: "rotation" - }; - - this.__placementTool = "multilayerPositionTool"; - - this.__toolParams = { - position: "position" - }; - - this.__mint = "LL CHAMBER"; - - this.__zOffsetKeys = { - FLOW: "height", - CONTROL: "height" - }; - - this.__substrateOffset = { - FLOW: "0", - CONTROL: "+1" - }; - } - - getPorts(params: { [k: string]: any }) { - const position = params.position; - const px = position[0]; - const py = position[1]; - const l = params.length; - const w = params.width; - const rotation = params.rotation; - const color = params.color; - // let radius = params["cornerRadius"]; - - const numArray = params.numberOfChambers; - const spacing = params.spacing; - - const ports = []; - - ports.push(new ComponentPort(w / 2, -w, "1", LogicalLayerType.FLOW)); - - ports.push(new ComponentPort(numArray * w + (numArray + 1) * spacing - w / 2, -w, "2", LogicalLayerType.FLOW)); - - ports.push(new ComponentPort(w / 2, l + w, "3", LogicalLayerType.FLOW)); - - ports.push(new ComponentPort(numArray * w + (numArray + 1) * spacing - w / 2, l + w, "4", LogicalLayerType.FLOW)); - - // //Control Ports - Left - ports.push(new ComponentPort(0, 0.2 * l, "10", LogicalLayerType.CONTROL)); - - ports.push(new ComponentPort(0, 0.5 * l, "9", LogicalLayerType.CONTROL)); - - ports.push(new ComponentPort(0, 0.8 * l, "8", LogicalLayerType.CONTROL)); - - // Control Ports - Right - ports.push(new ComponentPort(numArray * w + (numArray + 1) * spacing, 0.2 * l, "5", LogicalLayerType.CONTROL)); - - ports.push(new ComponentPort(numArray * w + (numArray + 1) * spacing, 0.5 * l, "6", LogicalLayerType.CONTROL)); - - ports.push(new ComponentPort(numArray * w + (numArray + 1) * spacing, 0.8 * l, "7", LogicalLayerType.CONTROL)); - - return ports; - } - - __renderFlow(params: { [k: string]: any }) { - const position = params.position; - const px = position[0]; - const py = position[1]; - const l = params.length; - const w = params.width; - const rotation = params.rotation; - const color = params.color; - // let radius = params["cornerRadius"]; - - const numArray = params.numberOfChambers; - const spacing = params.spacing; - - const rendered = new paper.CompoundPath(""); - - let rec; - - for (let i = 0; i < numArray; i++) { - rec = new paper.Path.Rectangle({ - point: new paper.Point(px + (i + 1) * spacing + i * w, py - 1), - size: [w, l + 2], - radius: 0 - }); - - rendered.addChild(rec); - } - - const topchannel = new paper.Path.Rectangle({ - point: new paper.Point(px, py - w), - size: [numArray * w + (numArray + 1) * spacing, w] - }); - - rendered.addChild(topchannel); - - const bottomchannel = new paper.Path.Rectangle({ - point: new paper.Point(px, py + l), - size: [numArray * w + (numArray + 1) * spacing, w] - }); - - rendered.addChild(bottomchannel); - - rendered.fillColor = color; - rendered.rotate(rotation, new paper.Point(px, py)); - return rendered; - } - - __renderControl(params: { [k: string]: any }) { - const rendered = new paper.CompoundPath(""); - const position = params.position; - const px = position[0]; - const py = position[1]; - const l = params.length; - const w = params.width; - const rotation = params.rotation; - const color = params.color; - // let radius = params["cornerRadius"]; - - const numArray = params.numberOfChambers; - const spacing = params.spacing; - - const topchannel = new paper.Path.Rectangle({ - point: new paper.Point(px, py + 0.2 * l - w / 2), - size: [numArray * w + (numArray + 1) * spacing, w] - }); - - rendered.addChild(topchannel); - - const middlechannel = new paper.Path.Rectangle({ - point: new paper.Point(px, py + 0.5 * l - w / 2), - size: [numArray * w + (numArray + 1) * spacing, w] - }); - - rendered.addChild(middlechannel); - - const bottomchannel = new paper.Path.Rectangle({ - point: new paper.Point(px, py + 0.8 * l - w / 2), - size: [numArray * w + (numArray + 1) * spacing, w] - }); - - rendered.addChild(bottomchannel); - - rendered.fillColor = color; - rendered.rotate(rotation, new paper.Point(px, py)); - return rendered; - } - - render2D(params: { [k: string]: any }, key = "FLOW") { - if (key === "FLOW") { - return this.__renderFlow(params); - } else if (key === "CONTROL") { - return this.__renderControl(params); - } - throw new Error("Unknown render key found in LLCHAMBER: " + key); - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - const ret = new paper.CompoundPath(""); - const flow = this.render2D(params, "FLOW"); - const control = this.render2D(params, "CONTROL"); - ret.addChild(control); - ret.addChild(flow); - ret.fillColor = params.color; - ret.fillColor!.alpha = 0.5; - return ret; - } -} diff --git a/src/app/library/logicArray.ts b/src/app/library/logicArray.ts deleted file mode 100755 index 85d0b783..00000000 --- a/src/app/library/logicArray.ts +++ /dev/null @@ -1,750 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class LogicArray extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - chamberWidth: "Float", - height: "Float", - chamberLength: "Float", - flowChannelWidth: "Float", - controlChannelWidth: "Float", - portRadius: "Float", - rotation: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - height: 1.1 * 1000, - chamberWidth: 1.5 * 1000, - chamberLength: 1.5 * 1000, - flowChannelWidth: 0.6 * 1000, - controlChannelWidth: 0.4 * 1000, - portRadius: 1000, - rotation: 0 - }; - - this.__units = { - componentSpacing: "μm", - chamberWidth: "μm", - chamberLength: "μm", - flowChannelWidth: "μm", - controlChannelWidth: "μm", - portRadius: "μm", - height: "μm", - rotation: "°" - }; - - this.__minimum = { - componentSpacing: 0, - height: 1, - chamberWidth: 1, - chamberLength: 1, - flowChannelWidth: 1, - controlChannelWidth: 1, - portRadius: 1, - rotation: 0 - }; - - this.__maximum = { - componentSpacing: 10000, - height: 1.1 * 10000, - chamberWidth: 10000, - chamberLength: 10000, - flowChannelWidth: 10000, - controlChannelWidth: 10000, - portRadius: 10000, - rotation: 360 - }; - - this.__placementTool = "multilayerPositionTool"; - - this.__toolParams = { - position: "position" - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - chamberWidth: "chamberWidth", - flowChannelWidth: "flowChannelWidth", - controlChannelWidth: "controlChannelWidth", - portRadius: "portRadius", - chamberLength: "chamberLength", - height: "height", - position: "position", - rotation: "rotation" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - chamberWidth: "chamberWidth", - flowChannelWidth: "flowChannelWidth", - controlChannelWidth: "controlChannelWidth", - portRadius: "portRadius", - chamberLength: "chamberLength", - height: "height", - rotation: "rotation" - }; - - this.__renderKeys = ["FLOW", "CONTROL", "CELL"]; - - this.__mint = "LOGIC ARRAY"; - - this.__zOffsetKeys = { - FLOW: "height", - CONTROL: "height", - CELL: "height" - }; - - this.__substrateOffset = { - FLOW: "0", - CONTROL: "+1", - CELL: "0" - }; - } - - render2D(params: { [k: string]: any }, key: string) { - if (key === "FLOW") { - return this.__drawFlow(params); - } else if (key === "CONTROL") { - return this.__drawControl(params); - } else if (key === "CELL") { - console.log("cell"); - return this.__drawCell(params); - } - throw new Error("Invalid key passed to LogicArray render2D"); - } - - __drawFlow(params: { [k: string]: any }) { - const x = params.position[0]; - const y = params.position[1]; - const color = params.color; - const spacing = params.componentSpacing; - const chamberWidth = params.chamberWidth; - const flowChannelWidth = params.flowChannelWidth; - const controlChannelWidth = params.controlChannelWidth; - const portRadius = params.portRadius; - const chamberLength = params.chamberLength; - const rotation = params.rotation; - - const ret = new paper.CompoundPath(""); - const topDistance = 14 * spacing; - const inWidth = 5 * spacing; - const pathLength = 20 * spacing; - const extraLength = 2 * spacing; - - // middle path - let topLeft = new paper.Point(x, y - flowChannelWidth / 2); - let bottomRight = new paper.Point(x + pathLength, y + flowChannelWidth / 2); - - let rec: paper.Rectangle | paper.PathItem = new paper.Path.Rectangle(topLeft, bottomRight); - - /// / left - topLeft = new paper.Point(x + (2 * inWidth) / 3 - controlChannelWidth, y - flowChannelWidth / 2 - controlChannelWidth); - bottomRight = new paper.Point(x + (2 * inWidth) / 3 + controlChannelWidth, y + flowChannelWidth / 2 + controlChannelWidth); - rec = rec.subtract(new paper.Path.Rectangle(topLeft, bottomRight)); - - /// / second left - topLeft = new paper.Point(x + inWidth + pathLength / 2 - extraLength - controlChannelWidth, y - flowChannelWidth / 2 - controlChannelWidth); - bottomRight = new paper.Point(x + inWidth + pathLength / 2 - extraLength + controlChannelWidth, y + flowChannelWidth / 2 + controlChannelWidth); - rec = rec.subtract(new paper.Path.Rectangle(topLeft, bottomRight)); - - /// / right - topLeft = new paper.Point(x + inWidth + pathLength / 2 + extraLength - controlChannelWidth, y - flowChannelWidth / 2 - controlChannelWidth); - bottomRight = new paper.Point(x + inWidth + pathLength / 2 + extraLength + controlChannelWidth, y + flowChannelWidth / 2 + controlChannelWidth); - rec = rec.subtract(new paper.Path.Rectangle(topLeft, bottomRight)); - ret.addChild(rec); - - // top part ** cut - topLeft = new paper.Point(x, y - topDistance - flowChannelWidth / 2); - bottomRight = new paper.Point(x + inWidth, y - topDistance + flowChannelWidth / 2); - - rec = new paper.Path.Rectangle(topLeft, bottomRight); - - topLeft = new paper.Point(x + inWidth / 3 - controlChannelWidth, y - topDistance - flowChannelWidth / 2 - controlChannelWidth); - bottomRight = new paper.Point(x + inWidth / 3 + controlChannelWidth, y - topDistance + flowChannelWidth / 2 + controlChannelWidth); - - const cutrec = new paper.Path.Rectangle(topLeft, bottomRight); - - rec = rec.subtract(cutrec); - - ret.addChild(rec); - - topLeft = new paper.Point(x + inWidth - flowChannelWidth / 2, y - topDistance - topDistance / 2); - bottomRight = new paper.Point(x + inWidth + flowChannelWidth / 2, y - topDistance + topDistance / 2); - - ret.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + inWidth, y - topDistance - topDistance / 2); - bottomRight = new paper.Point(x + inWidth + pathLength, y - topDistance - topDistance / 2 + flowChannelWidth); - - ret.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + inWidth + pathLength - flowChannelWidth, y - topDistance - topDistance / 2); - bottomRight = new paper.Point(x + inWidth + pathLength, y - topDistance + topDistance / 2); - - ret.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // top part bottom line ** cut for control - topLeft = new paper.Point(x + inWidth, y - topDistance + topDistance / 2 - flowChannelWidth); - bottomRight = new paper.Point(x + inWidth + pathLength, y - topDistance + topDistance / 2); - - rec = new paper.Path.Rectangle(topLeft, bottomRight); - - /// / left - topLeft = new paper.Point(x + pathLength / 2 - extraLength - controlChannelWidth, y - topDistance / 2 - flowChannelWidth - controlChannelWidth); - bottomRight = new paper.Point(x + pathLength / 2 - extraLength + controlChannelWidth, y - topDistance / 2 + controlChannelWidth); - rec = rec.subtract(new paper.Path.Rectangle(topLeft, bottomRight)); - - /// / second left - topLeft = new paper.Point(x + inWidth + pathLength / 2 - extraLength - controlChannelWidth, y - topDistance / 2 - flowChannelWidth - controlChannelWidth); - bottomRight = new paper.Point(x + inWidth + pathLength / 2 - extraLength + controlChannelWidth, y - topDistance / 2 + controlChannelWidth); - rec = rec.subtract(new paper.Path.Rectangle(topLeft, bottomRight)); - - /// / second right - topLeft = new paper.Point(x + inWidth + pathLength / 2 + extraLength - controlChannelWidth, y - topDistance / 2 - flowChannelWidth - controlChannelWidth); - bottomRight = new paper.Point(x + inWidth + pathLength / 2 + extraLength + controlChannelWidth, y - topDistance / 2 + controlChannelWidth); - rec = rec.subtract(new paper.Path.Rectangle(topLeft, bottomRight)); - - /// / right - topLeft = new paper.Point(x + 2 * inWidth + pathLength / 2 + extraLength - controlChannelWidth, y - topDistance / 2 - flowChannelWidth - controlChannelWidth); - bottomRight = new paper.Point(x + 2 * inWidth + pathLength / 2 + extraLength + controlChannelWidth, y - topDistance / 2 + controlChannelWidth); - rec = rec.subtract(new paper.Path.Rectangle(topLeft, bottomRight)); - ret.addChild(rec); - - // bottom part ** cut - topLeft = new paper.Point(x, y + topDistance + flowChannelWidth / 2); - bottomRight = new paper.Point(x + inWidth, y + topDistance - flowChannelWidth / 2); - - rec = new paper.Path.Rectangle(topLeft, bottomRight); - - topLeft = new paper.Point(x + inWidth / 3 - controlChannelWidth, y + topDistance - flowChannelWidth / 2 - controlChannelWidth); - bottomRight = new paper.Point(x + inWidth / 3 + controlChannelWidth, y + topDistance + flowChannelWidth / 2 + controlChannelWidth); - rec = rec.subtract(new paper.Path.Rectangle(topLeft, bottomRight)); - ret.addChild(rec); - - topLeft = new paper.Point(x + inWidth - flowChannelWidth / 2, y + topDistance + topDistance / 2); - bottomRight = new paper.Point(x + inWidth + flowChannelWidth / 2, y + topDistance - topDistance / 2); - - ret.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + inWidth, y + topDistance + topDistance / 2); - bottomRight = new paper.Point(x + inWidth + pathLength, y + topDistance + topDistance / 2 - flowChannelWidth); - - ret.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + inWidth + pathLength - flowChannelWidth, y + topDistance + topDistance / 2); - bottomRight = new paper.Point(x + inWidth + pathLength, y + topDistance - topDistance / 2); - - ret.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // bottom part top line ** cut for control - topLeft = new paper.Point(x + inWidth, y + topDistance - topDistance / 2 + flowChannelWidth); - bottomRight = new paper.Point(x + inWidth + pathLength, y + topDistance - topDistance / 2); - - rec = new paper.Path.Rectangle(topLeft, bottomRight); - - /// / left - topLeft = new paper.Point(x + pathLength / 2 - extraLength - controlChannelWidth, y + topDistance / 2 - controlChannelWidth); - bottomRight = new paper.Point(x + pathLength / 2 - extraLength + controlChannelWidth, y + topDistance / 2 + flowChannelWidth + controlChannelWidth); - rec = rec.subtract(new paper.Path.Rectangle(topLeft, bottomRight)); - - /// / second left - topLeft = new paper.Point(x + inWidth + pathLength / 2 - extraLength - controlChannelWidth, y + topDistance / 2 - controlChannelWidth); - bottomRight = new paper.Point(x + inWidth + pathLength / 2 - extraLength + controlChannelWidth, y + topDistance / 2 + flowChannelWidth + controlChannelWidth); - rec = rec.subtract(new paper.Path.Rectangle(topLeft, bottomRight)); - - /// / second right - topLeft = new paper.Point(x + inWidth + pathLength / 2 + extraLength - controlChannelWidth, y + topDistance / 2 - controlChannelWidth); - bottomRight = new paper.Point(x + inWidth + pathLength / 2 + extraLength + controlChannelWidth, y + topDistance / 2 + flowChannelWidth + controlChannelWidth); - rec = rec.subtract(new paper.Path.Rectangle(topLeft, bottomRight)); - - /// / right - topLeft = new paper.Point(x + 2 * inWidth + pathLength / 2 + extraLength - controlChannelWidth, y + topDistance / 2 - controlChannelWidth); - bottomRight = new paper.Point(x + 2 * inWidth + pathLength / 2 + extraLength + controlChannelWidth, y + topDistance / 2 + flowChannelWidth + controlChannelWidth); - rec = rec.subtract(new paper.Path.Rectangle(topLeft, bottomRight)); - ret.addChild(rec); - - // insde middle ** cut - topLeft = new paper.Point(x + inWidth + pathLength / 2 - flowChannelWidth / 2, y - topDistance / 2); - bottomRight = new paper.Point(x + inWidth + pathLength / 2 + flowChannelWidth / 2, y + topDistance / 2); - - rec = new paper.Path.Rectangle(topLeft, bottomRight); - - /// / top - topLeft = new paper.Point(x + inWidth + pathLength / 2 - flowChannelWidth / 2 - controlChannelWidth, y - topDistance / 2 + 4 * spacing - controlChannelWidth); - bottomRight = new paper.Point(x + inWidth + pathLength / 2 + flowChannelWidth / 2 + controlChannelWidth, y - topDistance / 2 + 4 * spacing + controlChannelWidth); - rec = rec.subtract(new paper.Path.Rectangle(topLeft, bottomRight)); - - /// / bottom - topLeft = new paper.Point(x + inWidth + pathLength / 2 - flowChannelWidth / 2 - controlChannelWidth, y + topDistance / 2 - 4 * spacing - controlChannelWidth); - bottomRight = new paper.Point(x + inWidth + pathLength / 2 + flowChannelWidth / 2 + controlChannelWidth, y + topDistance / 2 - 4 * spacing + controlChannelWidth); - rec = rec.subtract(new paper.Path.Rectangle(topLeft, bottomRight)); - ret.addChild(rec); - - // inside left ** cut - topLeft = new paper.Point(x + pathLength / 2 - flowChannelWidth / 2, y - topDistance - topDistance / 4); - bottomRight = new paper.Point(x + pathLength / 2 + flowChannelWidth / 2, y + topDistance + topDistance / 4); - - rec = new paper.Path.Rectangle(topLeft, bottomRight); - - /// / top - topLeft = new paper.Point(x + pathLength / 2 - flowChannelWidth / 2 - controlChannelWidth, y - topDistance / 2 - 5 * spacing - controlChannelWidth); - bottomRight = new paper.Point(x + pathLength / 2 + flowChannelWidth / 2 + controlChannelWidth, y - topDistance / 2 - 5 * spacing + controlChannelWidth); - rec = rec.subtract(new paper.Path.Rectangle(topLeft, bottomRight)); - - /// / second top - topLeft = new paper.Point(x + pathLength / 2 - flowChannelWidth / 2 - controlChannelWidth, y - topDistance / 2 + 3 * spacing - controlChannelWidth); - bottomRight = new paper.Point(x + pathLength / 2 + flowChannelWidth / 2 + controlChannelWidth, y - topDistance / 2 + 3 * spacing + controlChannelWidth); - rec = rec.subtract(new paper.Path.Rectangle(topLeft, bottomRight)); - - /// / second bottom - topLeft = new paper.Point(x + pathLength / 2 - flowChannelWidth / 2 - controlChannelWidth, y + topDistance / 2 - 3 * spacing - controlChannelWidth); - bottomRight = new paper.Point(x + pathLength / 2 + flowChannelWidth / 2 + controlChannelWidth, y + topDistance / 2 - 3 * spacing + controlChannelWidth); - rec = rec.subtract(new paper.Path.Rectangle(topLeft, bottomRight)); - - /// / bottom - topLeft = new paper.Point(x + pathLength / 2 - flowChannelWidth / 2 - controlChannelWidth, y + topDistance / 2 + 5 * spacing - controlChannelWidth); - bottomRight = new paper.Point(x + pathLength / 2 + flowChannelWidth / 2 + controlChannelWidth, y + topDistance / 2 + 5 * spacing + controlChannelWidth); - rec = rec.subtract(new paper.Path.Rectangle(topLeft, bottomRight)); - ret.addChild(rec); - - let circ = new paper.Path.Circle(new paper.Point(x + pathLength / 2, y - topDistance - topDistance / 4), portRadius); - - ret.addChild(circ); - - circ = new paper.Path.Circle(new paper.Point(x + pathLength / 2, y + topDistance + topDistance / 4), portRadius); - - ret.addChild(circ); - - // inside right ** cut - topLeft = new paper.Point(x + 2 * inWidth + pathLength / 2 - flowChannelWidth, y - topDistance - topDistance / 4); - bottomRight = new paper.Point(x + 2 * inWidth + pathLength / 2, y + topDistance + topDistance / 4); - - rec = new paper.Path.Rectangle(topLeft, bottomRight); - - /// / top - topLeft = new paper.Point(x + 2 * inWidth + pathLength / 2 - flowChannelWidth - controlChannelWidth, y - topDistance / 2 - 2 * spacing - controlChannelWidth); - bottomRight = new paper.Point(x + 2 * inWidth + pathLength / 2 + controlChannelWidth, y - topDistance / 2 - 2 * spacing + controlChannelWidth); - rec = rec.subtract(new paper.Path.Rectangle(topLeft, bottomRight)); - - /// / second top - topLeft = new paper.Point(x + 2 * inWidth + pathLength / 2 - flowChannelWidth - controlChannelWidth, y - topDistance / 2 + 5 * spacing - controlChannelWidth); - bottomRight = new paper.Point(x + 2 * inWidth + pathLength / 2 + controlChannelWidth, y - topDistance / 2 + 5 * spacing + controlChannelWidth); - rec = rec.subtract(new paper.Path.Rectangle(topLeft, bottomRight)); - - /// / second bottom - topLeft = new paper.Point(x + 2 * inWidth + pathLength / 2 - flowChannelWidth - controlChannelWidth, y + topDistance / 2 - 5 * spacing - controlChannelWidth); - bottomRight = new paper.Point(x + 2 * inWidth + pathLength / 2 + controlChannelWidth, y + topDistance / 2 - 5 * spacing + controlChannelWidth); - rec = rec.subtract(new paper.Path.Rectangle(topLeft, bottomRight)); - - /// / bottom - topLeft = new paper.Point(x + 2 * inWidth + pathLength / 2 - flowChannelWidth - controlChannelWidth, y + topDistance / 2 + 2 * spacing - controlChannelWidth); - bottomRight = new paper.Point(x + 2 * inWidth + pathLength / 2 + controlChannelWidth, y + topDistance / 2 + 2 * spacing + controlChannelWidth); - rec = rec.subtract(new paper.Path.Rectangle(topLeft, bottomRight)); - ret.addChild(rec); - - circ = new paper.Path.Circle(new paper.Point(x + 2 * inWidth + pathLength / 2 - flowChannelWidth / 2, y - topDistance - topDistance / 4), portRadius); - - ret.addChild(circ); - - circ = new paper.Path.Circle(new paper.Point(x + 2 * inWidth + pathLength / 2 - flowChannelWidth / 2, y + topDistance + topDistance / 4), portRadius); - - ret.addChild(circ); - - ret.fillColor = color; - ret.rotate(rotation, new paper.Point(x, y)); - return ret; - } - - __drawControl(params: { [k: string]: any }) { - const x = params.position[0]; - const y = params.position[1]; - const color = params.color; - const spacing = params.componentSpacing; - const chamberWidth = params.chamberWidth; - const flowChannelWidth = params.flowChannelWidth; - const controlChannelWidth = params.controlChannelWidth; - const portRadius = params.portRadius; - const chamberLength = params.chamberLength; - const rotation = params.rotation; - - const ret = new paper.CompoundPath(""); - const topDistance = 14 * spacing; - const inWidth = 5 * spacing; - const pathLength = 20 * spacing; - - const extraLength = 2 * spacing; - - const control = new paper.CompoundPath(""); - - // control 24 - let topLeft = new paper.Point(x + inWidth / 3 - controlChannelWidth / 2, y - topDistance - topDistance / 2 - extraLength); - let bottomRight = new paper.Point(x + inWidth / 3 + controlChannelWidth / 2, y - topDistance); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + inWidth / 3 - controlChannelWidth, y - topDistance - flowChannelWidth / 2 - controlChannelWidth); - bottomRight = new paper.Point(x + inWidth / 3 + controlChannelWidth, y - topDistance + flowChannelWidth / 2 + controlChannelWidth); - - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // cnotrol 25 - topLeft = new paper.Point(x + (2 * inWidth) / 3 - controlChannelWidth / 2, y - topDistance - topDistance / 2 - extraLength); - bottomRight = new paper.Point(x + (2 * inWidth) / 3 + controlChannelWidth / 2, y); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + (2 * inWidth) / 3 - controlChannelWidth, y - flowChannelWidth / 2 - controlChannelWidth); - bottomRight = new paper.Point(x + (2 * inWidth) / 3 + controlChannelWidth, y + flowChannelWidth / 2 + controlChannelWidth); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // control 26 - topLeft = new paper.Point(x + inWidth / 3 - controlChannelWidth / 2, y + topDistance + topDistance / 2 + extraLength); - bottomRight = new paper.Point(x + inWidth / 3 + controlChannelWidth / 2, y + topDistance); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + inWidth / 3 - controlChannelWidth, y + topDistance - flowChannelWidth / 2 - controlChannelWidth); - bottomRight = new paper.Point(x + inWidth / 3 + controlChannelWidth, y + topDistance + flowChannelWidth / 2 + controlChannelWidth); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // control 8 - topLeft = new paper.Point(x + 2 * inWidth + pathLength / 2 - flowChannelWidth / 2, y - topDistance / 2 - 2 * spacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + inWidth + pathLength + extraLength, y - topDistance / 2 - 2 * spacing + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + 2 * inWidth + pathLength / 2 - flowChannelWidth - controlChannelWidth, y - topDistance / 2 - 2 * spacing - controlChannelWidth); - bottomRight = new paper.Point(x + 2 * inWidth + pathLength / 2 + controlChannelWidth, y - topDistance / 2 - 2 * spacing + controlChannelWidth); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // control 7 - topLeft = new paper.Point(x + inWidth + pathLength / 2 + extraLength, y - topDistance / 2 - 3 * spacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + inWidth + pathLength + extraLength, y - topDistance / 2 - 3 * spacing + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + inWidth + pathLength / 2 + extraLength - controlChannelWidth / 2, y - topDistance / 2 - 3 * spacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + inWidth + pathLength / 2 + extraLength + controlChannelWidth / 2, y - topDistance / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + inWidth + pathLength / 2 + extraLength - controlChannelWidth, y - topDistance / 2 - flowChannelWidth - controlChannelWidth); - bottomRight = new paper.Point(x + inWidth + pathLength / 2 + extraLength + controlChannelWidth, y - topDistance / 2 + controlChannelWidth); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // control 6 - topLeft = new paper.Point(x + inWidth + pathLength / 2 - extraLength, y - topDistance / 2 - 4 * spacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + inWidth + pathLength + extraLength, y - topDistance / 2 - 4 * spacing + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + inWidth + pathLength / 2 - extraLength - controlChannelWidth / 2, y - topDistance / 2 - 4 * spacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + inWidth + pathLength / 2 - extraLength + controlChannelWidth / 2, y - topDistance / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + inWidth + pathLength / 2 - extraLength - controlChannelWidth, y - topDistance / 2 - flowChannelWidth - controlChannelWidth); - bottomRight = new paper.Point(x + inWidth + pathLength / 2 - extraLength + controlChannelWidth, y - topDistance / 2 + controlChannelWidth); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // control 5 - topLeft = new paper.Point(x + pathLength / 2, y - topDistance / 2 - 5 * spacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + inWidth + pathLength + extraLength, y - topDistance / 2 - 5 * spacing + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + pathLength / 2 - flowChannelWidth / 2 - controlChannelWidth, y - topDistance / 2 - 5 * spacing - controlChannelWidth); - bottomRight = new paper.Point(x + pathLength / 2 + flowChannelWidth / 2 + controlChannelWidth, y - topDistance / 2 - 5 * spacing + controlChannelWidth); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // control 4 - topLeft = new paper.Point(x + pathLength / 2 - extraLength, y - topDistance / 2 - 6 * spacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + inWidth + pathLength + extraLength, y - topDistance / 2 - 6 * spacing + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + pathLength / 2 - extraLength - controlChannelWidth / 2, y - topDistance / 2 - 6 * spacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + pathLength / 2 - extraLength + controlChannelWidth / 2, y - topDistance / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + pathLength / 2 - extraLength - controlChannelWidth, y - topDistance / 2 - flowChannelWidth - controlChannelWidth); - bottomRight = new paper.Point(x + pathLength / 2 - extraLength + controlChannelWidth, y - topDistance / 2 + controlChannelWidth); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // control 19 - topLeft = new paper.Point(x + 2 * inWidth + pathLength / 2 - flowChannelWidth / 2, y + topDistance / 2 + 2 * spacing + controlChannelWidth / 2); - bottomRight = new paper.Point(x + inWidth + pathLength + extraLength, y + topDistance / 2 + 2 * spacing - controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + 2 * inWidth + pathLength / 2 - flowChannelWidth - controlChannelWidth, y + topDistance / 2 + 2 * spacing - controlChannelWidth); - bottomRight = new paper.Point(x + 2 * inWidth + pathLength / 2 + controlChannelWidth, y + topDistance / 2 + 2 * spacing + controlChannelWidth); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // control 20 - topLeft = new paper.Point(x + inWidth + pathLength / 2 + extraLength, y + topDistance / 2 + 3 * spacing + controlChannelWidth / 2); - bottomRight = new paper.Point(x + inWidth + pathLength + extraLength, y + topDistance / 2 + 3 * spacing - controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + inWidth + pathLength / 2 + extraLength - controlChannelWidth / 2, y + topDistance / 2 + 3 * spacing + controlChannelWidth / 2); - bottomRight = new paper.Point(x + inWidth + pathLength / 2 + extraLength + controlChannelWidth / 2, y + topDistance / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + inWidth + pathLength / 2 + extraLength - controlChannelWidth, y + topDistance / 2 - controlChannelWidth); - bottomRight = new paper.Point(x + inWidth + pathLength / 2 + extraLength + controlChannelWidth, y + topDistance / 2 + flowChannelWidth + controlChannelWidth); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // control 21 - topLeft = new paper.Point(x + inWidth + pathLength / 2 - extraLength, y + topDistance / 2 + 4 * spacing + controlChannelWidth / 2); - bottomRight = new paper.Point(x + inWidth + pathLength + extraLength, y + topDistance / 2 + 4 * spacing - controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + inWidth + pathLength / 2 - extraLength - controlChannelWidth / 2, y + topDistance / 2 + 4 * spacing + controlChannelWidth / 2); - bottomRight = new paper.Point(x + inWidth + pathLength / 2 - extraLength + controlChannelWidth / 2, y + topDistance / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + inWidth + pathLength / 2 - extraLength - controlChannelWidth, y + topDistance / 2 - controlChannelWidth); - bottomRight = new paper.Point(x + inWidth + pathLength / 2 - extraLength + controlChannelWidth, y + topDistance / 2 + flowChannelWidth + controlChannelWidth); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // control 22 - topLeft = new paper.Point(x + pathLength / 2, y + topDistance / 2 + 5 * spacing + controlChannelWidth / 2); - bottomRight = new paper.Point(x + inWidth + pathLength + extraLength, y + topDistance / 2 + 5 * spacing - controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + pathLength / 2 - flowChannelWidth / 2 - controlChannelWidth, y + topDistance / 2 + 5 * spacing - controlChannelWidth); - bottomRight = new paper.Point(x + pathLength / 2 + flowChannelWidth / 2 + controlChannelWidth, y + topDistance / 2 + 5 * spacing + controlChannelWidth); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // control 23 - topLeft = new paper.Point(x + pathLength / 2 - extraLength, y + topDistance / 2 + 6 * spacing + controlChannelWidth / 2); - bottomRight = new paper.Point(x + inWidth + pathLength + extraLength, y + topDistance / 2 + 6 * spacing - controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + pathLength / 2 - extraLength - controlChannelWidth / 2, y + topDistance / 2 + 6 * spacing + controlChannelWidth / 2); - bottomRight = new paper.Point(x + pathLength / 2 - extraLength + controlChannelWidth / 2, y + topDistance / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + pathLength / 2 - extraLength - controlChannelWidth, y + topDistance / 2 - controlChannelWidth); - bottomRight = new paper.Point(x + pathLength / 2 - extraLength + controlChannelWidth, y + topDistance / 2 + flowChannelWidth + controlChannelWidth); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // control 9 - topLeft = new paper.Point(x + 2 * inWidth + pathLength / 2 + extraLength, y - topDistance / 2 + 2 * spacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + inWidth + pathLength + extraLength, y - topDistance / 2 + 2 * spacing + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + 2 * inWidth + pathLength / 2 + extraLength - controlChannelWidth / 2, y - topDistance / 2); - bottomRight = new paper.Point(x + 2 * inWidth + pathLength / 2 + extraLength + controlChannelWidth / 2, y - topDistance / 2 + 2 * spacing + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + 2 * inWidth + pathLength / 2 + extraLength - controlChannelWidth, y - topDistance / 2 - flowChannelWidth - controlChannelWidth); - bottomRight = new paper.Point(x + 2 * inWidth + pathLength / 2 + extraLength + controlChannelWidth, y - topDistance / 2 + controlChannelWidth); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // control 18 - topLeft = new paper.Point(x + 2 * inWidth + pathLength / 2 + extraLength, y + topDistance / 2 - 2 * spacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + inWidth + pathLength + extraLength, y + topDistance / 2 - 2 * spacing + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + 2 * inWidth + pathLength / 2 + extraLength - controlChannelWidth / 2, y + topDistance / 2); - bottomRight = new paper.Point(x + 2 * inWidth + pathLength / 2 + extraLength + controlChannelWidth / 2, y + topDistance / 2 - 2 * spacing - controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + 2 * inWidth + pathLength / 2 + extraLength - controlChannelWidth, y + topDistance / 2 - controlChannelWidth); - bottomRight = new paper.Point(x + 2 * inWidth + pathLength / 2 + extraLength + controlChannelWidth, y + topDistance / 2 + flowChannelWidth + controlChannelWidth); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // control 10 - topLeft = new paper.Point(x + pathLength / 2, y - topDistance / 2 + 3 * spacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + inWidth + pathLength + extraLength, y - topDistance / 2 + 3 * spacing + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + pathLength / 2 - flowChannelWidth / 2 - controlChannelWidth, y - topDistance / 2 + 3 * spacing - controlChannelWidth); - bottomRight = new paper.Point(x + pathLength / 2 + flowChannelWidth / 2 + controlChannelWidth, y - topDistance / 2 + 3 * spacing + controlChannelWidth); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // control 17 - topLeft = new paper.Point(x + pathLength / 2, y + topDistance / 2 - 3 * spacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + inWidth + pathLength + extraLength, y + topDistance / 2 - 3 * spacing + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + pathLength / 2 - flowChannelWidth / 2 - controlChannelWidth, y + topDistance / 2 - 3 * spacing - controlChannelWidth); - bottomRight = new paper.Point(x + pathLength / 2 + flowChannelWidth / 2 + controlChannelWidth, y + topDistance / 2 - 3 * spacing + controlChannelWidth); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // control 11 - topLeft = new paper.Point(x + inWidth + pathLength / 2, y - topDistance / 2 + 4 * spacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + inWidth + pathLength + extraLength, y - topDistance / 2 + 4 * spacing + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + inWidth + pathLength / 2 - flowChannelWidth / 2 - controlChannelWidth, y - topDistance / 2 + 4 * spacing - controlChannelWidth); - bottomRight = new paper.Point(x + inWidth + pathLength / 2 + flowChannelWidth / 2 + controlChannelWidth, y - topDistance / 2 + 4 * spacing + controlChannelWidth); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // control 16 - topLeft = new paper.Point(x + inWidth + pathLength / 2, y + topDistance / 2 - 4 * spacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + inWidth + pathLength + extraLength, y + topDistance / 2 - 4 * spacing + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + inWidth + pathLength / 2 - flowChannelWidth / 2 - controlChannelWidth, y + topDistance / 2 - 4 * spacing - controlChannelWidth); - bottomRight = new paper.Point(x + inWidth + pathLength / 2 + flowChannelWidth / 2 + controlChannelWidth, y + topDistance / 2 - 4 * spacing + controlChannelWidth); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // control 12 - topLeft = new paper.Point(x + 2 * inWidth + pathLength / 2, y - topDistance / 2 + 5 * spacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + inWidth + pathLength + extraLength, y - topDistance / 2 + 5 * spacing + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + 2 * inWidth + pathLength / 2 - flowChannelWidth - controlChannelWidth, y - topDistance / 2 + 5 * spacing - controlChannelWidth); - bottomRight = new paper.Point(x + 2 * inWidth + pathLength / 2 + controlChannelWidth, y - topDistance / 2 + 5 * spacing + controlChannelWidth); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // control 15 - topLeft = new paper.Point(x + 2 * inWidth + pathLength / 2, y + topDistance / 2 - 5 * spacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + inWidth + pathLength + extraLength, y + topDistance / 2 - 5 * spacing + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + 2 * inWidth + pathLength / 2 - flowChannelWidth - controlChannelWidth, y + topDistance / 2 - 5 * spacing - controlChannelWidth); - bottomRight = new paper.Point(x + 2 * inWidth + pathLength / 2 + controlChannelWidth, y + topDistance / 2 - 5 * spacing + controlChannelWidth); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // control 13 - topLeft = new paper.Point(x + inWidth + pathLength / 2 - extraLength, y - topDistance / 2 + 6 * spacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + inWidth + pathLength + extraLength, y - topDistance / 2 + 6 * spacing + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + inWidth + pathLength / 2 - extraLength - controlChannelWidth / 2, y - topDistance / 2 + 6 * spacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + inWidth + pathLength / 2 - extraLength + controlChannelWidth / 2, y + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + inWidth + pathLength / 2 - extraLength - controlChannelWidth, y - flowChannelWidth / 2 - controlChannelWidth); - bottomRight = new paper.Point(x + inWidth + pathLength / 2 - extraLength + controlChannelWidth, y + flowChannelWidth / 2 + controlChannelWidth); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // control 14 - topLeft = new paper.Point(x + inWidth + pathLength / 2 + extraLength, y + topDistance / 2 - 6 * spacing - controlChannelWidth / 2); - bottomRight = new paper.Point(x + inWidth + pathLength + extraLength, y + topDistance / 2 - 6 * spacing + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + inWidth + pathLength / 2 + extraLength - controlChannelWidth / 2, y); - bottomRight = new paper.Point(x + inWidth + pathLength / 2 + extraLength + controlChannelWidth / 2, y + topDistance / 2 - 6 * spacing + controlChannelWidth / 2); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(x + inWidth + pathLength / 2 + extraLength - controlChannelWidth, y - flowChannelWidth / 2 - controlChannelWidth); - bottomRight = new paper.Point(x + inWidth + pathLength / 2 + extraLength + controlChannelWidth, y + flowChannelWidth / 2 + controlChannelWidth); - control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - control.fillColor = color; - control.rotate(rotation, new paper.Point(x, y)); - - return control; - } - - getPorts(params: { [k: string]: any }) { - const ports = []; - const chamberWidth = params.chamberWidth; - const flowChannelWidth = params.flowChannelWidth; - const controlChannelWidth = params.controlChannelWidth; - const portRadius = params.portRadius; - const chamberLength = params.chamberLength; - const rotation = params.rotation; - const spacing = params.componentSpacing; - - const topDistance = 14 * spacing; - const inWidth = 5 * spacing; - const pathLength = 20 * spacing; - - const extraLength = 2 * spacing; - - // flow - ports.push(new ComponentPort(0, -topDistance, "1", LogicalLayerType.FLOW)); - ports.push(new ComponentPort(0, 0, "2", LogicalLayerType.FLOW)); - ports.push(new ComponentPort(0, topDistance, "3", LogicalLayerType.FLOW)); - - // control - ports.push(new ComponentPort(inWidth + pathLength + extraLength, -topDistance / 2 - 6 * spacing, "4", LogicalLayerType.CONTROL)); - ports.push(new ComponentPort(inWidth + pathLength + extraLength, -topDistance / 2 - 5 * spacing, "5", LogicalLayerType.CONTROL)); - ports.push(new ComponentPort(inWidth + pathLength + extraLength, -topDistance / 2 - 4 * spacing, "6", LogicalLayerType.CONTROL)); - ports.push(new ComponentPort(inWidth + pathLength + extraLength, -topDistance / 2 - 3 * spacing, "7", LogicalLayerType.CONTROL)); - ports.push(new ComponentPort(inWidth + pathLength + extraLength, -topDistance / 2 - 2 * spacing, "8", LogicalLayerType.CONTROL)); - ports.push(new ComponentPort(inWidth + pathLength + extraLength, -topDistance / 2 + 2 * spacing, "9", LogicalLayerType.CONTROL)); - ports.push(new ComponentPort(inWidth + pathLength + extraLength, -topDistance / 2 + 3 * spacing, "10", LogicalLayerType.CONTROL)); - ports.push(new ComponentPort(inWidth + pathLength + extraLength, -topDistance / 2 + 4 * spacing, "11", LogicalLayerType.CONTROL)); - ports.push(new ComponentPort(inWidth + pathLength + extraLength, -topDistance / 2 + 5 * spacing, "12", LogicalLayerType.CONTROL)); - ports.push(new ComponentPort(inWidth + pathLength + extraLength, -topDistance / 2 + 6 * spacing, "13", LogicalLayerType.CONTROL)); - ports.push(new ComponentPort(inWidth + pathLength + extraLength, topDistance / 2 - 6 * spacing, "14", LogicalLayerType.CONTROL)); - ports.push(new ComponentPort(inWidth + pathLength + extraLength, topDistance / 2 - 5 * spacing, "15", LogicalLayerType.CONTROL)); - ports.push(new ComponentPort(inWidth + pathLength + extraLength, topDistance / 2 - 4 * spacing, "16", LogicalLayerType.CONTROL)); - ports.push(new ComponentPort(inWidth + pathLength + extraLength, topDistance / 2 - 3 * spacing, "17", LogicalLayerType.CONTROL)); - ports.push(new ComponentPort(inWidth + pathLength + extraLength, topDistance / 2 - 2 * spacing, "18", LogicalLayerType.CONTROL)); - ports.push(new ComponentPort(inWidth + pathLength + extraLength, topDistance / 2 + 2 * spacing, "19", LogicalLayerType.CONTROL)); - ports.push(new ComponentPort(inWidth + pathLength + extraLength, topDistance / 2 + 3 * spacing, "20", LogicalLayerType.CONTROL)); - ports.push(new ComponentPort(inWidth + pathLength + extraLength, topDistance / 2 + 4 * spacing, "21", LogicalLayerType.CONTROL)); - ports.push(new ComponentPort(inWidth + pathLength + extraLength, topDistance / 2 + 5 * spacing, "22", LogicalLayerType.CONTROL)); - ports.push(new ComponentPort(inWidth + pathLength + extraLength, topDistance / 2 + 6 * spacing, "23", LogicalLayerType.CONTROL)); - ports.push(new ComponentPort(inWidth / 3, -topDistance - topDistance / 2 - extraLength, "24", LogicalLayerType.CONTROL)); - ports.push(new ComponentPort((2 * inWidth) / 3, -topDistance - topDistance / 2 - extraLength, "25", LogicalLayerType.CONTROL)); - ports.push(new ComponentPort(inWidth / 3, topDistance + topDistance / 2 + extraLength, "26", LogicalLayerType.CONTROL)); - - return ports; - } - - __drawCell(params: { [k: string]: any }) { - const x = params.position[0]; - const y = params.position[1]; - const color = params.color; - const spacing = params.componentSpacing; - const chamberWidth = params.chamberWidth; - const flowChannelWidth = params.flowChannelWidth; - const controlChannelWidth = params.controlChannelWidth; - const portRadius = params.portRadius; - const chamberLength = params.chamberLength; - const rotation = params.rotation; - - const ret = new paper.CompoundPath(""); - const topDistance = 14 * spacing; - const inWidth = 5 * spacing; - const pathLength = 20 * spacing; - - const extraLength = 2 * spacing; - - const cell = new paper.CompoundPath(""); - - // top left - let topLeft = new paper.Point(x + pathLength / 2 - chamberWidth / 2, y - topDistance / 2 - chamberLength / 2 - flowChannelWidth / 2); - let bottomRight = new paper.Point(x + pathLength / 2 + chamberWidth / 2, y - topDistance / 2 + chamberLength / 2 - flowChannelWidth / 2); - cell.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // top right - topLeft = new paper.Point(x + 2 * inWidth + pathLength / 2 - chamberWidth / 2 - flowChannelWidth / 2, y - topDistance / 2 - chamberLength / 2 - flowChannelWidth / 2); - bottomRight = new paper.Point(x + 2 * inWidth + pathLength / 2 + chamberWidth / 2 - flowChannelWidth / 2, y - topDistance / 2 + chamberLength / 2 - flowChannelWidth / 2); - cell.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // bottom left - topLeft = new paper.Point(x + pathLength / 2 - chamberWidth / 2, y + topDistance / 2 - chamberLength / 2 + flowChannelWidth / 2); - bottomRight = new paper.Point(x + pathLength / 2 + chamberWidth / 2, y + topDistance / 2 + chamberLength / 2 + flowChannelWidth / 2); - cell.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // top right - topLeft = new paper.Point(x + 2 * inWidth + pathLength / 2 - chamberWidth / 2 - flowChannelWidth / 2, y + topDistance / 2 - chamberLength / 2 + flowChannelWidth / 2); - bottomRight = new paper.Point(x + 2 * inWidth + pathLength / 2 + chamberWidth / 2 - flowChannelWidth / 2, y + topDistance / 2 + chamberLength / 2 + flowChannelWidth / 2); - cell.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - cell.fillColor = color; - cell.rotate(rotation, new paper.Point(x, y)); - - return cell; - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - const render = this.__drawFlow(params); - render.addChild(this.__drawControl(params)); - render.addChild(this.__drawCell(params)); - - render.fillColor!.alpha = 0.5; - return render; - } -} diff --git a/src/app/library/merger.ts b/src/app/library/merger.ts deleted file mode 100644 index d45d83dd..00000000 --- a/src/app/library/merger.ts +++ /dev/null @@ -1,267 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class Merger extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - rotation: "Float", - height: "Float", - inletWidth: "Float", - inletLength: "Float", - electrodeWidth: "Float", - electrodeLength: "Float", - electrodeDistance: "Float", - outletWidth: "Float", - outletLength: "Float", - chamberHeight: "Float", - chamberLength: "Float", - channelDepth: "Float", - electrodeDepth: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - rotation: 0, - height: 250, - inletWidth: 2 * 1000, - inletLength: 4 * 1000, - electrodeWidth: 1000, - electrodeLength: 5 * 1000, - electrodeDistance: 1000, - outletWidth: 2 * 1000, - outletLength: 4 * 1000, - chamberHeight: 2.7 * 1000, - chamberLength: 2 * 1000, - channelDepth: 1000, - electrodeDepth: 1000 - }; - - this.__units = { - componentSpacing: "μm", - rotation: "°", - height: "μm", - inletWidth: "μm", - inletLength: "μm", - electrodeWidth: "μm", - electrodeLength: "μm", - electrodeDistance: "μm", - outletWidth: "μm", - outletLength: "μm", - chamberHeight: "μm", - chamberLength: "μm", - channelDepth: "μm", - electrodeDepth: "μm" - }; - - this.__minimum = { - componentSpacing: 0, - rotation: 0, - height: 10, - inletWidth: 1000, - inletLength: 1000, - electrodeWidth: 500, - electrodeLength: 3 * 1000, - electrodeDistance: 500, - outletWidth: 1000, - outletLength: 1000, - chamberHeight: 1000, - chamberLength: 1000, - channelDepth: 1000, - electrodeDepth: 1000 - }; - - this.__maximum = { - componentSpacing: 10000, - rotation: 360, - height: 1200, - inletWidth: 3 * 1000, - inletLength: 6 * 1000, - electrodeWidth: 3 * 1000, - electrodeLength: 7 * 1000, - electrodeDistance: 1500, - outletWidth: 3 * 1000, - outletLength: 6 * 1000, - chamberHeight: 4 * 1000, - chamberLength: 4 * 1000, - channelDepth: 1000, - electrodeDepth: 1000 - }; - - this.__placementTool = "multilayerPositionTool"; - - this.__toolParams = { - cursorPosition: "position" - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - rotation: "rotation", - inletWidth: "inletWidth", - inletLength: "inletLength", - electrodeWidth: "electrodeWidth", - electrodeLength: "electrodeLength", - electrodeDistance: "electrodeDistance", - outletWidth: "outletWidth", - outletLength: "outletLength", - chamberHeight: "chamberHeight", - chamberLength: "chamberLength", - channelDepth: "channelDepth", - electrodeDepth: "electrodeDepth" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - rotation: "rotation", - inletWidth: "inletWidth", - inletLength: "inletLength", - electrodeWidth: "electrodeWidth", - electrodeLength: "electrodeLength", - electrodeDistance: "electrodeDistance", - outletWidth: "outletWidth", - outletLength: "outletLength", - chamberHeight: "chamberHeight", - chamberLength: "chamberLength", - channelDepth: "channelDepth", - electrodeDepth: "electrodeDepth" - }; - - this.__renderKeys = ["FLOW", "INTEGRATION"]; - - this.__mint = "DROPLET MERGER"; - - this.__zOffsetKeys = { - FLOW: "height", - INTEGRATION: "electrodeDepth" - }; - - this.__substrateOffset = { - FLOW: "0", - INTEGRATION: "+1" - }; - } - - getPorts(params: { [k: string]: any }) { - const inletLength = params.inletLength; - const outletLength = params.outletLength; - const chamberLength = params.chamberLength; - - const ports = []; - - ports.push(new ComponentPort(0, 0, "1", LogicalLayerType.FLOW)); - - ports.push(new ComponentPort(inletLength + chamberLength + outletLength, 0, "2", LogicalLayerType.FLOW)); - - return ports; - } - - __renderFlow(params: { [k: string]: any }) { - const rotation = params.rotation; - const x = params.position[0]; - const y = params.position[1]; - const color = params.color; - const inletWidth = params.inletWidth; - const inletLength = params.inletLength; - const outletWidth = params.outletWidth; - const outletLength = params.outletLength; - const chamberHeight = params.chamberHeight; - const chamberLength = params.chamberLength; - const channelDepth = params.channelDepth; - const electrodeDepth = params.electrodeDepth; - - const serp = new paper.CompoundPath(""); - - // inlet - let topLeft = new paper.Point(x, y - inletWidth / 2); - let bottomRight = new paper.Point(x + inletLength, y + inletWidth / 2); - - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // merge chamber - topLeft = new paper.Point(x + inletLength, y - chamberHeight / 2); - bottomRight = new paper.Point(x + inletLength + chamberLength, y + chamberHeight / 2); - - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // outlet - topLeft = new paper.Point(x + inletLength + chamberLength, y - outletWidth / 2); - bottomRight = new paper.Point(x + inletLength + chamberLength + outletLength, y + outletWidth / 2); - - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - serp.rotate(rotation, new paper.Point(x, y)); - - serp.fillColor = color; - return serp; - } - - __renderIntegrate(params: { [k: string]: any }) { - const rotation = params.rotation; - const x = params.position[0]; - const y = params.position[1]; - const color = params.color; - const inletLength = params.inletLength; - const electrodeWidth = params.electrodeWidth; - const electrodeLength = params.electrodeLength; - const electrodeDistance = params.electrodeDistance; - const channelDepth = params.channelDepth; - const electrodeDepth = params.electrodeDepth; - - const serp = new paper.CompoundPath(""); - - // left electrode - let topLeft = new paper.Point(x + inletLength, y - electrodeLength / 2); - let bottomRight = new paper.Point(x + inletLength + electrodeWidth, y + electrodeLength / 2); - - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // right electrode - topLeft = new paper.Point(x + inletLength + electrodeWidth + electrodeDistance, y - electrodeLength / 2); - bottomRight = new paper.Point(x + inletLength + 2 * electrodeWidth + electrodeDistance, y + electrodeLength / 2); - - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - serp.rotate(rotation, new paper.Point(x, y)); - - serp.fillColor = color; - return serp; - } - - // render2DTarget(key, params) { - // const serp = this.render2D(params, key); - - // serp.fillColor.alpha = 0.5; - // return serp; - // } - - render2D(params: { [k: string]: any }, key = "FLOW") { - if (key === "FLOW") { - return this.__renderFlow(params); - } else if (key === "INTEGRATION") { - return this.__renderIntegrate(params); - } - throw new Error("Unknown render key found in DROPLET MERGER: " + key); - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - const ret = new paper.CompoundPath(""); - const flow = this.render2D(params, "FLOW"); - const integrate = this.render2D(params, "INTEGRATION"); - ret.addChild(integrate); - ret.addChild(flow); - ret.fillColor = params.color; - ret.fillColor!.alpha = 0.5; - return ret; - } -} diff --git a/src/app/library/mux.ts b/src/app/library/mux.ts deleted file mode 100755 index 28d53cda..00000000 --- a/src/app/library/mux.ts +++ /dev/null @@ -1,496 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class Mux extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - flowChannelWidth: "Float", - rotation: "Float", - spacing: "Float", - in: "Integer", - out: "Integer", - width: "Float", - length: "Float", - height: "Float", - stageLength: "Float", - controlChannelWidth: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - flowChannelWidth: 0.8 * 1000, - rotation: 0, - spacing: 4 * 1000, - in: 1, - out: 8, - width: 1.6 * 1000, - length: 1.6 * 1000, - height: 250, - stageLength: 4000, - controlChannelWidth: 0.4 * 1000 - }; - - this.__units = { - componentSpacing: "μm", - flowChannelWidth: "μm", - rotation: "°", - spacing: "μm", - in: "", - out: "", - width: "μm", - length: "μm", - height: "μm", - stageLength: "μm", - controlChannelWidth: "μm" - }; - - this.__minimum = { - componentSpacing: 0, - flowChannelWidth: 10, - spacing: 30, - in: 1, - out: 2, - width: 60, - length: 60, - height: 10, - stageLength: 100, - controlChannelWidth: 10, - rotation: 0 - }; - - this.__maximum = { - componentSpacing: 10000, - flowChannelWidth: 2000, - spacing: 12000, - in: 1, - out: 128, - width: 12 * 1000, - length: 12 * 1000, - height: 1200, - stageLength: 6000, - controlChannelWidth: 2000, - rotation: 360 - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - flowChannelWidth: "flowChannelWidth", - controlChannelWidth: "controlChannelWidth", - rotation: "rotation", - spacing: "spacing", - width: "width", - length: "length", - in: "in", - out: "out", - stageLength: "stageLength" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - position: "position", - flowChannelWidth: "flowChannelWidth", - controlChannelWidth: "controlChannelWidth", - rotation: "rotation", - spacing: "spacing", - width: "width", - length: "length", - in: "in", - out: "out", - stageLength: "stageLength" - }; - - this.__placementTool = "multilayerPositionTool"; - - this.__toolParams = { - position: "position" - }; - - this.__renderKeys = ["FLOW", "CONTROL"]; - - this.__mint = "MUX"; - - this.__zOffsetKeys = { - FLOW: "height", - CONTROL: "height" - }; - - this.__substrateOffset = { - FLOW: "0", - CONTROL: "+1" - }; - } - - __drawFlow(params: { [k: string]: any }): paper.CompoundPath { - const position = params.position; - const cw = params.flowChannelWidth; - let rotation = params.rotation; - const spacing = params.spacing; - const ins = params.in; - const outs = params.out; - let leafs; - if (ins < outs) { - leafs = outs; - } else { - leafs = ins; - rotation += 180; - } - const color = params.color; - const stagelength = params.stageLength; - const px = position[0]; - const py = position[1]; - - const levels = Math.ceil(Math.log2(leafs)); - let isodd = false; // This is used to figure out how many lines have to be made - if (leafs % 2 === 0) { - isodd = false; - } else { - isodd = true; - } - const w = spacing * (leafs / 2 + 1); - const l = (levels + 1) * stagelength; - - // console.log("CW: " + cw + " levels: "+ levels + " width: " + w + " length: " + l) - - const treepath = new paper.CompoundPath(""); - - this.__generateMuxTwig(treepath, px, py, cw, stagelength, w, 1, levels); - - // Draw the tree - - treepath.fillColor = color; - return (treepath.rotate(rotation, new paper.Point(px, py)) as unknown) as paper.CompoundPath; - } - - __drawControl(params: { [k: string]: any }): paper.CompoundPath { - const position = params.position; - const cw = params.flowChannelWidth; - const ctlcw = params.controlChannelWidth; - let rotation = params.rotation; - const spacing = params.spacing; - const ins = params.in; - const outs = params.out; - let leafs; - if (ins < outs) { - leafs = outs; - } else { - leafs = ins; - rotation += 180; - } - const color = params.color; - const stagelength = params.stageLength; - const valvelength = params.length; - const valvewidth = params.width; - const px = position[0]; - const py = position[1]; - - const treeWidth = (leafs - 1) * spacing + leafs * cw + leafs * valvewidth; - const leftEdge = px - treeWidth / 2; - const rightEdge = px + treeWidth / 2; - - const levels = Math.ceil(Math.log2(leafs)); - - const isodd = !(leafs % 2); - const w = spacing * (leafs / 2 + 1); - const l = (levels + 1) * stagelength; - - // console.log("CW: " + cw + " levels: "+ levels + " width: " + w + " length: " + l) - - const treepath = new paper.CompoundPath(""); - - this.__generateMuxControlTwig(treepath, px, py, cw, ctlcw, stagelength, w, 1, levels, valvewidth, valvelength, leftEdge, rightEdge); - - // Draw the tree - - treepath.fillColor = color; - return (treepath.rotate(rotation, new paper.Point(px, py)) as unknown) as paper.CompoundPath; - } - - getPorts(params: { [k: string]: any }) { - const ports = []; - const cw = params.flowChannelWidth; - const spacing = params.spacing; - const ins = params.in; - const outs = params.out; - let leafs; - if (ins < outs) { - leafs = outs; - } else { - leafs = ins; - } - const stagelength = params.stageLength; - - const levels = Math.ceil(Math.log2(leafs)); - const w = spacing * (leafs / 2 + 1); - - const length = levels * (cw + stagelength) + stagelength; - const width = 2 * 0.5 * w * 2 * Math.pow(0.5, levels); - - ports.push(new ComponentPort(0, 0, "1", LogicalLayerType.FLOW)); - - for (let i = 0; i < leafs; i++) { - ports.push(new ComponentPort(((leafs - 1) * width) / 2 - i * width, length, (2 + i).toString(), LogicalLayerType.FLOW)); - } - - let count = 2 + leafs; - const lstartx = -0.5 * (cw + spacing); - const lendx = lstartx + cw; - const lstarty = stagelength + cw; - const lendy = lstarty + stagelength; - - const lcenterx = (lstartx + lendx) / 2; - const lcentery = lstarty + Math.abs(lstarty - lendy) / 4; - const valvewidth = params.width; - - const treeWidth = (leafs - 1) * spacing + leafs * cw + valvewidth; - - const leftEdge = -treeWidth / 2; - const rightEdge = treeWidth / 2; - - const rstartx = 0.5 * (spacing - cw); - const rendx = rstartx + cw; - const rstarty = stagelength + cw; - const rendy = rstarty + stagelength; - - const rcenterx = (rstartx + rendx) / 2; - const rcentery = rstarty + (Math.abs(rstarty - rendy) * 3) / 4; - - for (let i = 0; i < Math.log2(leafs); i++) { - ports.push(new ComponentPort(leftEdge, i * (cw + stagelength) + lcentery, count.toString(), LogicalLayerType.CONTROL)); - count++; - ports.push(new ComponentPort(rightEdge, i * (cw + stagelength) + rcentery, count.toString(), LogicalLayerType.CONTROL)); - count++; - } - - return ports; - } - - render2D(params: { [k: string]: any }, key: string): paper.CompoundPath { - if (key === "FLOW") { - return this.__drawFlow(params); - } else if (key === "CONTROL") { - return this.__drawControl(params); - } - throw new Error("Unknown key: " + key); - } - - render2DTarget(key: string | null, params: { [k: string]: any }): paper.CompoundPath { - const render = this.render2D(params, "FLOW"); - render?.addChild(this.render2D(params, "CONTROL") as paper.Item); - render!.fillColor!.alpha = 0.5; - return render; - } - - __generateMuxTwig(treepath: paper.CompoundPath, px: number, py: number, cw: number, stagelength: number, newspacing: number, level: number, maxlevel: number, islast = false): void { - // var newspacing = 2 * (spacing + cw); - const hspacing = newspacing / 2; - const lex = px - 0.5 * newspacing; - const ley = py + cw + stagelength; - const rex = px + 0.5 * newspacing; - const rey = py + cw + stagelength; - - if (level === maxlevel) { - islast = true; - // console.log("Final Spacing: " + newspacing) - } - - this.__drawmuxtwig(treepath, px, py, cw, stagelength, newspacing, islast); - - if (!islast) { - this.__generateMuxTwig(treepath, lex, ley, cw, stagelength, hspacing, level + 1, maxlevel); - this.__generateMuxTwig(treepath, rex, rey, cw, stagelength, hspacing, level + 1, maxlevel); - } - } - - __drawmuxtwig(treepath: paper.CompoundPath, px: number, py: number, cw: number, stagelength: number, spacing: number, drawleafs = false): paper.CompoundPath { - // stem - let startPoint = new paper.Point(px - cw / 2, py); - let endPoint = new paper.Point(px + cw / 2, py + stagelength); - let rec = new paper.Path.Rectangle({ - from: startPoint, - to: endPoint, - radius: 0, - strokeWidth: 0 - }); - - treepath.addChild(rec); - - // Draw 2 leafs - // left leaf - const lstartx = px - 0.5 * (cw + spacing); - const lendx = lstartx + cw; - const lstarty = py + stagelength + cw; - const lendy = lstarty + stagelength; - - // //right leaf - const rstartx = px + 0.5 * (spacing - cw); - const rendx = rstartx + cw; - const rstarty = py + stagelength + cw; - const rendy = rstarty + stagelength; - - if (drawleafs) { - startPoint = new paper.Point(lstartx, lstarty); - endPoint = new paper.Point(lendx, lendy); - rec = new paper.Path.Rectangle({ - from: startPoint, - to: endPoint, - radius: 0, - strokeWidth: 0 - }); - treepath.addChild(rec); - - startPoint = new paper.Point(rstartx, rstarty); - endPoint = new paper.Point(rendx, rendy); - rec = new paper.Path.Rectangle({ - from: startPoint, - to: endPoint, - radius: 0, - strokeWidth: 0 - }); - treepath.addChild(rec); - } - - // Horizontal bar - const hstartx = px - 0.5 * (cw + spacing); - const hendx = rendx; - const hstarty = py + stagelength; - const hendy = hstarty + cw; - startPoint = new paper.Point(hstartx, hstarty); - endPoint = new paper.Point(hendx, hendy); - rec = new paper.Path.Rectangle({ - from: startPoint, - to: endPoint, - radius: 0, - strokeWidth: 0 - }); - treepath.addChild(rec); - return treepath; - } - - __generateMuxControlTwig( - treepath: paper.CompoundPath, - px: number, - py: number, - cw: number, - ctlcw: number, - stagelength: number, - newspacing: number, - level: number, - maxlevel: number, - valvewidth: number, - valvelength: number, - leftEdge: number, - rightEdge: number, - islast = false - ): void { - // var newspacing = 2 * (spacing + cw); - const hspacing = newspacing / 2; - const lex = px - 0.5 * newspacing; - const ley = py + cw + stagelength; - const rex = px + 0.5 * newspacing; - const rey = py + cw + stagelength; - - if (level === maxlevel) { - islast = true; - // console.log("Final Spacing: " + newspacing) - } - - this.__drawmuxcontroltwig(treepath, px, py, cw, ctlcw, stagelength, newspacing, valvewidth, valvelength, leftEdge, rightEdge, islast); - - if (!islast) { - this.__generateMuxControlTwig(treepath, lex, ley, cw, ctlcw, stagelength, hspacing, level + 1, maxlevel, valvewidth, valvelength, leftEdge, rightEdge); - this.__generateMuxControlTwig(treepath, rex, rey, cw, ctlcw, stagelength, hspacing, level + 1, maxlevel, valvewidth, valvelength, leftEdge, rightEdge); - } - } - - __drawmuxcontroltwig( - treepath: paper.CompoundPath, - px: number, - py: number, - cw: number, - ctlcw: number, - stagelength: number, - spacing: number, - valvewidth: number, - valvelength: number, - leftEdge: number, - rightEdge: number, - drawleafs = false - ): paper.CompoundPath { - // stem - don't bother with valves - - // Draw 2 valves - // left leaf - const lstartx = px - 0.5 * (cw + spacing); - const lendx = lstartx + cw; - const lstarty = py + stagelength + cw; - const lendy = lstarty + stagelength; - - const lcenterx = (lstartx + lendx) / 2; - const lcentery = lstarty + Math.abs(lstarty - lendy) / 4; - - // //right leaf - const rstartx = px + 0.5 * (spacing - cw); - const rendx = rstartx + cw; - const rstarty = py + stagelength + cw; - const rendy = rstarty + stagelength; - - const rcenterx = (rstartx + rendx) / 2; - const rcentery = rstarty + (Math.abs(rstarty - rendy) * 3) / 4; - - let startPoint = new paper.Point(lcenterx - valvewidth / 2, lcentery - valvelength / 2); - let endPoint = new paper.Point(lcenterx + valvewidth / 2, lcentery + valvewidth / 2); - let rec = new paper.Path.Rectangle({ - from: startPoint, - to: endPoint, - radius: 0, - strokeWidth: 0 - }); - treepath.addChild(rec); - - const leftChannelStart = new paper.Point(startPoint.x, lcentery - ctlcw / 2); - const leftChannelEnd = new paper.Point(leftEdge, lcentery + ctlcw / 2); - - const leftChannel = new paper.Path.Rectangle({ - from: leftChannelStart, - to: leftChannelEnd, - radius: 0, - strokeWidth: 0 - }); - treepath.addChild(leftChannel); - - startPoint = new paper.Point(rcenterx - valvewidth / 2, rcentery - valvelength / 2); - endPoint = new paper.Point(rcenterx + valvewidth / 2, rcentery + valvewidth / 2); - rec = new paper.Path.Rectangle({ - from: startPoint, - to: endPoint, - radius: 0, - strokeWidth: 0 - }); - - treepath.addChild(rec); - const rightChannelStart = new paper.Point(endPoint.x, rcentery - ctlcw / 2); - const rightChannelEnd = new paper.Point(rightEdge, rcentery + ctlcw / 2); - - const rightChannel = new paper.Path.Rectangle({ - from: rightChannelStart, - to: rightChannelEnd, - radius: 0, - strokeWidth: 0 - }); - treepath.addChild(rightChannel); - - return treepath; - } -} diff --git a/src/app/library/node.ts b/src/app/library/node.ts deleted file mode 100755 index d0f30936..00000000 --- a/src/app/library/node.ts +++ /dev/null @@ -1,91 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class Node extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - height: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - height: 100 - }; - - this.__units = { - componentSpacing: "μm", - height: "μm" - }; - - this.__minimum = { - componentSpacing: 10, - height: 10 - }; - - this.__maximum = { - componentSpacing: 10000, - height: 1000 - }; - - this.__placementTool = "componentPositionTool"; - - this.__toolParams = { - position: "position" - }; - - this.__featureParams = { - componentSpacing: "componentSpacing" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing" - }; - - this.__renderKeys = ["FLOW"]; - - this.__mint = "NODE"; - - this.__zOffsetKeys = { - FLOW: "height" - }; - - this.__substrateOffset = { - FLOW: "0" - }; - } - - getPorts(params: { [k: string]: any }) { - const ports = []; - - ports.push(new ComponentPort(0, 0, "1", LogicalLayerType.FLOW)); - - return ports; - } - - render2D(params: { [k: string]: any }, key: string) { - // Regardless of the key... - const pos = new paper.Point(0, 0); - const outerCircle = new paper.Path.Circle(pos, 0); - return outerCircle; - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - if (key === null) { - key = this.__renderKeys[0]; - } - const render = this.render2D(params, key); - render.fillColor!.alpha = 0.5; - return render; - } -} diff --git a/src/app/library/picoinjection.ts b/src/app/library/picoinjection.ts deleted file mode 100644 index 559e284f..00000000 --- a/src/app/library/picoinjection.ts +++ /dev/null @@ -1,259 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class PicoInjection extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - height: "Float", - width: "Float", - injectorWidth: "Float", - injectorLength: "Float", - dropletWidth: "Float", - nozzleWidth: "Float", - nozzleLength: "Float", - electrodeDistance: "Float", - electrodeWidth: "Float", - electrodeLength: "Float", - rotation: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - height: 250, - width: 10 * 1000, - injectorWidth: 2 * 1000, - injectorLength: 3 * 1000, - dropletWidth: 0.8 * 1000, - nozzleWidth: 0.4 * 1000, - nozzleLength: 0.4 * 1000, - electrodeDistance: 0.8 * 1000, - electrodeWidth: 0.8 * 1000, - electrodeLength: 3 * 1000, - rotation: 0 - }; - - this.__units = { - componentSpacing: "μm", - height: "μm", - width: "μm", - injectorWidth: "μm", - injectorLength: "μm", - dropletWidth: "μm", - nozzleWidth: "μm", - nozzleLength: "μm", - electrodeDistance: "μm", - electrodeWidth: "μm", - electrodeLength: "μm", - rotation: "°" - }; - - this.__minimum = { - componentSpacing: 0, - height: 10, - width: 5 * 1000, - injectorWidth: 1000, - injectorLength: 1000, - dropletWidth: 100, - nozzleWidth: 80, - nozzleLength: 80, - electrodeDistance: 100, - electrodeWidth: 100, - electrodeLength: 1000, - rotation: 0 - }; - - this.__maximum = { - componentSpacing: 10000, - height: 1200, - width: 20 * 1000, - injectorWidth: 4000, - injectorLength: 5000, - dropletWidth: 2000, - nozzleWidth: 1000, - nozzleLength: 500, - electrodeDistance: 2000, - electrodeWidth: 2000, - electrodeLength: 5000, - rotation: 360 - }; - - this.__placementTool = "multilayerPositionTool"; - - this.__toolParams = { - cursorPosition: "position" - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - width: "width", - injectorWidth: "injectorWidth", - injectorLength: "injectorLength", - dropletWidth: "dropletWidth", - nozzleWidth: "nozzleWidth", - nozzleLength: "nozzleLength", - electrodeDistance: "electrodeDistance", - electrodeWidth: "electrodeWidth", - electrodeLength: "electrodeLength", - rotation: "rotation" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - width: "width", - injectorWidth: "injectorWidth", - injectorLength: "injectorLength", - dropletWidth: "dropletWidth", - nozzleWidth: "nozzleWidth", - nozzleLength: "nozzleLength", - electrodeDistance: "electrodeDistance", - electrodeWidth: "electrodeWidth", - electrodeLength: "electrodeLength", - rotation: "rotation" - }; - - this.__renderKeys = ["FLOW", "INTEGRATION"]; - - this.__mint = "PICOINJECTOR"; - - this.__zOffsetKeys = { - FLOW: "height", - INTEGRATION: "height" - }; - - this.__substrateOffset = { - FLOW: "0", - INTEGRATION: "0" - }; - } - - getPorts(params: { [k: string]: any }) { - const width = params.width; - const injectorLength = params.injectorLength; - const dropletWidth = params.dropletWidth; - const nozzleLength = params.nozzleLength; - const electrodeDistance = params.electrodeDistance; - const electrodeWidth = params.electrodeWidth; - const electrodeLength = params.electrodeLength; - - const ports = []; - - // droplet channel - ports.push(new ComponentPort(-width / 2, 0, "1", LogicalLayerType.FLOW)); - ports.push(new ComponentPort(width / 2, 0, "2", LogicalLayerType.FLOW)); - - // injector - ports.push(new ComponentPort(0, -dropletWidth / 2 - nozzleLength - injectorLength, "3", LogicalLayerType.FLOW)); - - return ports; - } - - __renderFlow(params: { [k: string]: any }) { - const rotation = params.rotation; - const x = params.position[0]; - const y = params.position[1]; - const color = params.color; - const width = params.width; - const injectorWidth = params.injectorWidth; - const injectorLength = params.injectorLength; - const dropletWidth = params.dropletWidth; - const nozzleWidth = params.nozzleWidth; - const nozzleLength = params.nozzleLength; - const serp = new paper.CompoundPath(""); - - // droplet channel - let topLeft = new paper.Point(x - width / 2, y - dropletWidth / 2); - let bottomRight = new paper.Point(x + width / 2, y + dropletWidth / 2); - - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // nozzle - topLeft = new paper.Point(x - nozzleWidth / 2, y - dropletWidth / 2 - nozzleLength); - bottomRight = new paper.Point(x + nozzleWidth / 2, y - dropletWidth / 2); - - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // injector - topLeft = new paper.Point(x - injectorWidth / 2, y - dropletWidth / 2 - nozzleLength - injectorLength); - bottomRight = new paper.Point(x + injectorWidth / 2, y - dropletWidth / 2 - nozzleLength); - - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - serp.rotate(rotation, new paper.Point(x, y)); - - serp.fillColor = color; - return serp; - } - - __renderIntegrate(params: { [k: string]: any }) { - const rotation = params.rotation; - const x = params.position[0]; - const y = params.position[1]; - const color = params.color; - const electrodeDistance = params.electrodeDistance; - const electrodeWidth = params.electrodeWidth; - const electrodeLength = params.electrodeLength; - const serp = new paper.CompoundPath(""); - - // middle electrode - let topLeft = new paper.Point(x - electrodeWidth / 2, y + electrodeDistance); - let bottomRight = new paper.Point(x + electrodeWidth / 2, y + electrodeDistance + electrodeLength); - - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // left electrode - topLeft = new paper.Point(x - electrodeWidth / 2 - 2 * electrodeWidth, y + electrodeDistance); - bottomRight = new paper.Point(x + electrodeWidth / 2 - 2 * electrodeWidth, y + electrodeDistance + electrodeLength); - - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // right electrode - topLeft = new paper.Point(x - electrodeWidth / 2 + 2 * electrodeWidth, y + electrodeDistance); - bottomRight = new paper.Point(x + electrodeWidth / 2 + 2 * electrodeWidth, y + electrodeDistance + electrodeLength); - - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - serp.rotate(rotation, new paper.Point(x, y)); - - serp.fillColor = color; - return serp; - } - - // render2DTarget(key, params) { - // const serp = this.render2D(params, key); - - // serp.fillColor.alpha = 0.5; - // return serp; - // } - - render2D(params: { [k: string]: any }, key = "FLOW") { - if (key === "FLOW") { - return this.__renderFlow(params); - } else if (key === "INTEGRATION") { - return this.__renderIntegrate(params); - } - throw new Error("Unknown render key found in PICOINJECTOR: " + key); - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - const ret = new paper.CompoundPath(""); - const flow = this.render2D(params, "FLOW"); - const integrate = this.render2D(params, "INTEGRATION"); - ret.addChild(integrate); - ret.addChild(flow); - ret.fillColor = params.color; - ret.fillColor!.alpha = 0.5; - return ret; - } -} diff --git a/src/app/library/port.ts b/src/app/library/port.ts deleted file mode 100644 index 6de0fb25..00000000 --- a/src/app/library/port.ts +++ /dev/null @@ -1,105 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class Port extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - portRadius: "Float", - height: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - portRadius: 0.7 * 1000, - height: 1.1 * 1000 - }; - - this.__units = { - componentSpacing: "μm", - portRadius: "μm", - height: "μm" - }; - - this.__minimum = { - componentSpacing: 0, - portRadius: 0.8 * 10, - height: 10 - }; - - this.__maximum = { - componentSpacing: 10000, - portRadius: 3000, - height: 1200 - }; - - this.__placementTool = "componentPositionTool"; - - this.__toolParams = { - position: "position" - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - portRadius: "portRadius" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - portRadius: "portRadius" - }; - - this.__renderKeys = ["FLOW"]; - - this.__mint = "PORT"; - - this.__zOffsetKeys = { - FLOW: "height" - }; - - this.__substrateOffset = { - FLOW: "0" - }; - } - - render2D(params: { [k: string]: any }, key: string) { - // Regardless of the key... - const position = params.position; - const radius = params.portRadius; - const color1 = params.color; - const pos = new paper.Point(position[0], position[1]); - const outerCircle = new paper.Path.Circle(pos, radius); - outerCircle.fillColor = color1; - return outerCircle; - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - if (key === null) { - key = this.__renderKeys[0]; - } - const render = this.render2D(params, key); - render.fillColor!.alpha = 0.5; - return render; - } - - getPorts(params: { [k: string]: any }) { - const radius = params.portRadius; - - const ports = []; - - ports.push(new ComponentPort(0, 0, "1", LogicalLayerType.FLOW)); - - return ports; - } -} diff --git a/src/app/library/pump.ts b/src/app/library/pump.ts deleted file mode 100644 index a98bb0f8..00000000 --- a/src/app/library/pump.ts +++ /dev/null @@ -1,228 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class Pump extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - rotation: "Float", - length: "Float", - width: "Float", - height: "Float", - spacing: "Float", - flowChannelWidth: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - rotation: 0, - width: 600, - length: 300, - height: 250, - spacing: 1000, - flowChannelWidth: 300 - }; - - this.__units = { - componentSpacing: "μm", - rotation: "°", - length: "μm", - width: "μm", - height: "μm", - spacing: "μm", - flowChannelWidth: "μm" - }; - - this.__minimum = { - componentSpacing: 0, - rotation: 0, - width: 30, - length: 120, - height: 10, - spacing: 10, - flowChannelWidth: 1 - }; - - this.__maximum = { - componentSpacing: 10000, - rotation: 360, - width: 6000, - length: 24 * 1000, - height: 1200, - spacing: 10000, - flowChannelWidth: 10000 - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - length: "length", - width: "width", - rotation: "rotation", - spacing: "spacing", - flowChannelWidth: "flowChannelWidth" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - length: "length", - width: "width", - rotation: "rotation", - spacing: "spacing", - flowChannelWidth: "flowChannelWidth" - }; - - this.__placementTool = "multilayerPositionTool"; - - this.__toolParams = { - position: "position" - }; - - this.__renderKeys = ["FLOW", "CONTROL"]; - - this.__mint = "PUMP"; - - this.__zOffsetKeys = { - FLOW: "height", - CONTROL: "height" - }; - - this.__substrateOffset = { - FLOW: "0", - CONTROL: "+1" - }; - } - - getPorts(params: { [k: string]: any }) { - const l = params.length; - const w = params.width; - const spacing = params.spacing; - - const ports = []; - ports.push(new ComponentPort(0, -l / 2 - spacing, "1", LogicalLayerType.FLOW)); - ports.push(new ComponentPort(0, l / 2 + spacing, "2", LogicalLayerType.FLOW)); - ports.push(new ComponentPort(0, -spacing, "3", LogicalLayerType.CONTROL)); - ports.push(new ComponentPort(0, 0, "4", LogicalLayerType.CONTROL)); - ports.push(new ComponentPort(0, spacing, "5", LogicalLayerType.CONTROL)); - - return ports; - } - - __drawFlow(params: { [k: string]: any }) { - let rec; - const position = params.position; - const px = position[0]; - const py = position[1]; - const l = params.length; - const w = params.width; - const color = params.color; - const rotation = params.rotation; - const spacing = params.spacing; - const channelwidth = params.flowChannelWidth; - - const startX = px - w / 2; - const startY = py - l / 2; - const endX = px + w / 2; - const endY = py + l / 2; - - const ret = new paper.CompoundPath(""); - - const startPoint = new paper.Point(startX, startY); - const endPoint = new paper.Point(endX, endY); - - rec = new paper.Path.Rectangle({ - from: new paper.Point(px - channelwidth / 2, py - spacing - l / 2), - to: new paper.Point(px + channelwidth / 2, py + spacing + l / 2) - }); - - ret.addChild(rec); - - ret.fillColor = color; - ret.rotate(rotation, new paper.Point(px, py)); - return ret; - } - - __drawControl(params: { [k: string]: any }) { - let rec; - const position = params.position; - const px = position[0]; - const py = position[1]; - const l = params.length; - const w = params.width; - const color = params.color; - const rotation = params.rotation; - const spacing = params.spacing; - - const startX = px - w / 2; - const startY = py - l / 2; - const endX = px + w / 2; - const endY = py + l / 2; - - const ret = new paper.CompoundPath(""); - - const startPoint = new paper.Point(startX, startY); - const endPoint = new paper.Point(endX, endY); - - rec = new paper.Path.Rectangle({ - from: startPoint, - to: endPoint, - radius: 0, - fillColor: color, - strokeWidth: 0 - }); - - ret.addChild(rec); - - const topcenter = new paper.Point(px, py - spacing); - - rec = new paper.Path.Rectangle({ - from: new paper.Point(topcenter.x - w / 2, topcenter.y - l / 2), - to: new paper.Point(topcenter.x + w / 2, topcenter.y + l / 2) - }); - - ret.addChild(rec); - - const bottomcenter = new paper.Point(px, py + spacing); - rec = new paper.Path.Rectangle({ - from: new paper.Point(bottomcenter.x - w / 2, bottomcenter.y - l / 2), - to: new paper.Point(bottomcenter.x + w / 2, bottomcenter.y + l / 2) - }); - - ret.addChild(rec); - - ret.fillColor = color; - ret.rotate(rotation, new paper.Point(px, py)); - return ret; - } - - render2D(params: { [k: string]: any }, key = "FLOW") { - if (key === "FLOW") { - return this.__drawFlow(params); - } else if (key === "CONTROL") { - return this.__drawControl(params); - } - - throw new Error("Unknown key: " + key); - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - const ret = new paper.CompoundPath(""); - const flow = this.render2D(params, "FLOW"); - const control = this.render2D(params, "CONTROL"); - ret.addChild(control as paper.Item); - ret.addChild(flow as paper.Item); - ret.fillColor = params.color; - ret.fillColor!.alpha = 0.5; - return ret; - } -} diff --git a/src/app/library/pump3D.ts b/src/app/library/pump3D.ts deleted file mode 100644 index e1546834..00000000 --- a/src/app/library/pump3D.ts +++ /dev/null @@ -1,281 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class Pump3D extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - valveRadius: "Float", - height: "Float", - gap: "Float", - rotation: "Float", - spacing: "Float", - flowChannelWidth: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - valveRadius: 1.2 * 1000, - height: 250, - gap: 0.6 * 1000, - width: 2.4 * 1000, - length: 2.4 * 1000, - rotation: 90, - spacing: 5000, - flowChannelWidth: 300 - }; - - this.__units = { - componentSpacing: "μm", - valveRadius: "μm", - height: "μm", - gap: "μm", - width: "μm", - length: "μm", - rotation: "°", - spacing: "μm", - flowChannelWidth: "μm" - }; - - this.__minimum = { - componentSpacing: 0, - valveRadius: 0.1 * 100, - height: 0.1 * 100, - gap: 0.5 * 10, - rotation: 0, - spacing: 10, - flowChannelWidth: 1 - }; - - this.__maximum = { - componentSpacing: 10000, - valveRadius: 0.2 * 10000, - height: 1.2 * 1000, - gap: 0.1 * 10000, - rotation: 360, - spacing: 10000, - flowChannelWidth: 10000 - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - rotation: "rotation", - valveRadius: "valveRadius", - flowChannelWidth: "flowChannelWidth", - spacing: "spacing", - gap: "gap" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - rotation: "rotation", - valveRadius: "valveRadius", - flowChannelWidth: "flowChannelWidth", - spacing: "spacing", - gap: "gap" - }; - - this.__placementTool = "multilayerPositionTool"; - - this.__toolParams = { - position: "position" - }; - - this.__renderKeys = ["FLOW", "CONTROL", "INVERSE"]; - - this.__mint = "PUMP3D"; - - this.__zOffsetKeys = { - FLOW: "height", - CONTROL: "height", - INVERSE: "height" - }; - - this.__substrateOffset = { - FLOW: "0", - CONTROL: "+1", - INVERSE: "0" - }; - } - - getPorts(params: { [k: string]: any }) { - const radius = params.valveRadius; - const spacing = params.spacing; - - const ports = []; - - ports.push(new ComponentPort(0, -spacing - radius, "1", LogicalLayerType.FLOW)); - ports.push(new ComponentPort(0, spacing + radius, "2", LogicalLayerType.FLOW)); - - ports.push(new ComponentPort(0, -spacing, "3", LogicalLayerType.CONTROL)); - - ports.push(new ComponentPort(0, 0, "4", LogicalLayerType.CONTROL)); - - ports.push(new ComponentPort(0, spacing, "5", LogicalLayerType.CONTROL)); - return ports; - } - - render2D(params: { [k: string]: any }, key = "FLOW") { - if (key === "FLOW") { - return this.__drawFlow(params); - } else if (key === "CONTROL") { - return this.__drawControl(params); - } else if (key === "INVERSE") { - return this.__drawInverse(params); - } - throw new Error("Unknown key: " + key); - - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - const ret = new paper.CompoundPath(""); - const flow = this.render2D(params, "FLOW"); - const control = this.render2D(params, "CONTROL"); - ret.addChild(control as paper.Item); - ret.addChild(flow as paper.Item); - ret.fillColor = params.color; - ret.fillColor!.alpha = 0.5; - return ret; - } - - __drawFlow(params: { [k: string]: any }) { - let valve; - let cutout; - let circ; - let center; - const ret = new paper.CompoundPath(""); - - const position = params.position; - const gap = params.gap; - const radius = params.valveRadius; - const color = params.color; - const rotation = params.rotation; - const spacing = params.spacing; - const channelwidth = params.flowChannelWidth; - - center = new paper.Point(position[0], position[1]); - // let h0p0, h0p1, h0p2, h1p0, h1p1, h1p2; - circ = new paper.Path.Circle(center, radius); - // circ.fillColor = color; - // if (String(color) === "3F51B5") { - cutout = new paper.Path.Rectangle({ - from: new paper.Point(position[0] - radius, position[1] - gap / 2), - to: new paper.Point(position[0] + radius, position[1] + gap / 2) - }); - // cutout.fillColor = "white"; - valve = circ.subtract(cutout); - ret.addChild(valve); - - const bottomcenter = new paper.Point(position[0], position[1] + spacing); - circ = new paper.Path.Circle(bottomcenter, radius); - // circ.fillColor = color; - // if (String(color) === "3F51B5") { - cutout = new paper.Path.Rectangle({ - from: new paper.Point(bottomcenter.x - radius, bottomcenter.y - gap / 2), - to: new paper.Point(bottomcenter.x + radius, bottomcenter.y + gap / 2) - }); - // cutout.fillColor = "white"; - valve = circ.subtract(cutout); - ret.addChild(valve); - - const topcenter = new paper.Point(position[0], position[1] - spacing); - - circ = new paper.Path.Circle(topcenter, radius); - // circ.fillColor = color; - // if (String(color) === "3F51B5") { - cutout = new paper.Path.Rectangle({ - from: new paper.Point(topcenter.x - radius, topcenter.y - gap / 2), - to: new paper.Point(topcenter.x + radius, topcenter.y + gap / 2) - }); - // cutout.fillColor = "white"; - valve = circ.subtract(cutout); - ret.addChild(valve); - - // Create the channels that go through - const bottomchannel = new paper.Path.Rectangle({ - from: new paper.Point(bottomcenter.x - channelwidth / 2, bottomcenter.y - gap / 2), - to: new paper.Point(center.x + channelwidth / 2, center.y + gap / 2) - }); - - ret.addChild(bottomchannel); - - const topchannel = new paper.Path.Rectangle({ - from: new paper.Point(topcenter.x - channelwidth / 2, topcenter.y + gap / 2), - to: new paper.Point(center.x + channelwidth / 2, center.y - gap / 2) - }); - - ret.addChild(topchannel); - - ret.rotate(rotation, center); - ret.fillColor = color; - - return ret; - } - - __drawControl(params: { [k: string]: any }) { - let circ; - const position = params.position; - const radius = params.valveRadius; - const color = params.color; - const rotation = params.rotation; - const spacing = params.spacing; - - const ret = new paper.CompoundPath(""); - - const center = new paper.Point(position[0], position[1]); - - circ = new paper.Path.Circle(center, radius); - ret.addChild(circ); - - const topcenter = new paper.Point(position[0], position[1] - spacing); - circ = new paper.Path.Circle(topcenter, radius); - ret.addChild(circ); - - const bottomcenter = new paper.Point(position[0], position[1] + spacing); - circ = new paper.Path.Circle(bottomcenter, radius); - ret.addChild(circ); - - ret.rotate(rotation, center); - ret.fillColor = color; - return ret; - } - - __drawInverse(params: { [k: string]: any }) { - let circ; - const position = params.position; - const radius = params.valveRadius; - const color = params.color; - const rotation = params.rotation; - const spacing = params.spacing; - - const ret = new paper.CompoundPath(""); - - const center = new paper.Point(position[0], position[1]); - - circ = new paper.Path.Circle(center, radius); - ret.addChild(circ); - - const topcenter = new paper.Point(position[0], position[1] - spacing); - circ = new paper.Path.Circle(topcenter, radius); - ret.addChild(circ); - - const bottomcenter = new paper.Point(position[0], position[1] + spacing); - circ = new paper.Path.Circle(bottomcenter, radius); - ret.addChild(circ); - - ret.rotate(rotation, center); - ret.fillColor = color; - return ret; - } -} diff --git a/src/app/library/rectValve.ts b/src/app/library/rectValve.ts deleted file mode 100644 index 717806cd..00000000 --- a/src/app/library/rectValve.ts +++ /dev/null @@ -1,95 +0,0 @@ -import Template from "./template"; -import paper from "paper"; - -export default class RectValve extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - portRadius: "Float", - height: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - portRadius: 0.7 * 1000, - height: 250 - }; - - this.__units = { - componentSpacing: "μm", - portRadius: "μm", - height: "μm" - }; - - this.__minimum = { - componentSpacing: 0, - portRadius: 0.8 * 10, - height: 10 - }; - - this.__maximum = { - componentSpacing: 10000, - portRadius: 2000, - height: 1200 - }; - - this.__placementTool = "componentPositionTool"; - - this.__toolParams = { - position: "position" - }; - - this.__renderKeys = ["FLOW", "CONTROL"]; - - this.__mint = "VALVE"; - - this.__zOffsetKeys = { - FLOW: "height", - CONTROL: "height" - }; - - this.__substrateOffset = { - FLOW: "0", - CONTROL: "+1" - }; - } - - render2D(params: { [k: string]: any }, key: string) { - // Regardless of the key... - const start = params.start; - const end = params.end; - const color = params.color; - const width = params.width; - const baseColor = params.baseColor; - const startPoint = new paper.Point(start[0], start[1]); - const endPoint = new paper.Point(end[0], end[1]); - const vec = endPoint.subtract(startPoint); - const rec = new paper.Path.Rectangle({ - size: [vec.length, width], - point: start, - // radius: width/2, - fillColor: color, - strokeWidth: 0 - }); - rec.translate(([0, -width / 2] as unknown) as paper.Point); - rec.rotate(vec.angle, start); - return rec; - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - if (key === null) { - key = this.__renderKeys[0]; - } - const render = this.render2D(params, key); - render.fillColor!.alpha = 0.5; - return render; - } -} diff --git a/src/app/library/rotaryMixer.ts b/src/app/library/rotaryMixer.ts deleted file mode 100755 index bc258b20..00000000 --- a/src/app/library/rotaryMixer.ts +++ /dev/null @@ -1,308 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class RotaryMixer extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - rotation: "Float", - radius: "Float", - flowChannelWidth: "Float", - controlChannelWidth: "Float", - valveWidth: "Float", - valveLength: "Float", - valveSpacing: "Float", - height: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - rotation: 0, - radius: 2000, - flowChannelWidth: 1000, - controlChannelWidth: 500, - valveWidth: 2.4 * 1000, - valveLength: 1 * 1000, - valveSpacing: 300, - valveRadius: 1.2 * 1000, - height: 250 - }; - - this.__units = { - componentSpacing: "μm", - rotation: "°", - radius: "μm", - flowChannelWidth: "μm", - controlChannelWidth: "μm", - valveWidth: "μm", - valveLength: "μm", - valveSpacing: "μm", - height: "μm" - }; - - this.__minimum = { - componentSpacing: 0, - radius: 0.1 * 5000, - flowChannelWidth: 0.1 * 1000, - controlChannelWidth: 0.1 * 1000, - valveWidth: 0.1 * 2.4 * 1000, - valveLength: 0.1 * 2.4 * 1000, - valveSpacing: 0.1 * 300, - valveRadius: 0.1 * 1.2 * 1000, - height: 0.1 * 200, - rotation: 0 - }; - - this.__maximum = { - componentSpacing: 10000, - radius: 10 * 5000, - flowChannelWidth: 10 * 1000, - controlChannelWidth: 10 * 1000, - valveWidth: 10 * 2.4 * 1000, - valveLength: 10 * 2.4 * 1000, - valveSpacing: 10 * 300, - valveRadius: 10 * 1.2 * 1000, - height: 10 * 200, - rotation: 360 - }; - - this.__placementTool = "multilayerPositionTool"; - - this.__toolParams = { - position: "position" - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - rotation: "rotation", - flowChannelWidth: "flowChannelWidth", - controlChannelWidth: "controlChannelWidth", - radius: "radius", - valveWidth: "valveWidth", - valveLength: "valveLength", - valveSpacing: "valveSpacing", - height: "height" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - position: "position", - rotation: "rotation", - flowChannelWidth: "flowChannelWidth", - controlChannelWidth: "controlChannelWidth", - radius: "radius", - valveWidth: "valveWidth", - valveLength: "valveLength", - valveSpacing: "valveSpacing", - height: "height" - }; - - this.__renderKeys = ["FLOW", "CONTROL"]; - - this.__mint = "ROTARY MIXER"; - - this.__zOffsetKeys = { - FLOW: "height", - CONTROL: "height" - }; - - this.__substrateOffset = { - FLOW: "0", - CONTROL: "+1" - }; - } - - getPorts(params: { [k: string]: any }) { - const radius = params.radius; - const valvespacing = params.valveSpacing; - const valvelength = params.valveLength; - const valvewidth = params.valveWidth; - const flowChannelWidth = params.flowChannelWidth; // params["flowChannelWidth"]; - const channellength = radius + valvelength + 2 * valvespacing + flowChannelWidth; // This needs to be a real expression - - const ports = []; - - ports.push(new ComponentPort(channellength, -radius - flowChannelWidth / 2, "1", LogicalLayerType.FLOW)); - ports.push(new ComponentPort(-channellength, radius + flowChannelWidth / 2, "2", LogicalLayerType.FLOW)); - - // top right - ports.push( - new ComponentPort(radius + flowChannelWidth + valvespacing + valvelength / 2, -radius - flowChannelWidth / 2 - valvewidth, "3", LogicalLayerType.CONTROL) - ); - // top bottom - ports.push(new ComponentPort(0, -radius - flowChannelWidth / 2 - valvewidth, "4", LogicalLayerType.CONTROL)); - // middle right - ports.push(new ComponentPort(flowChannelWidth / 2 + radius + valvewidth, 0, "5", LogicalLayerType.CONTROL)); - // bottom middle - ports.push(new ComponentPort(0, radius + flowChannelWidth / 2 + valvewidth, "6", LogicalLayerType.CONTROL)); - // bottom left - ports.push( - new ComponentPort(-radius - valvespacing - valvelength - flowChannelWidth / 2, radius + flowChannelWidth / 2 + valvewidth, "7", LogicalLayerType.CONTROL) - ); - - return ports; - } - - render2D(params: { [k: string]: any }, key: string) { - if (key === "FLOW") { - return this.__renderFlow(params); - } else if (key === "CONTROL") { - return this.__renderControl(params); - } - throw new Error("No valid key found"); - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - const rotarymixer_flow = this.__renderFlow(params); - const rotarymixer_control = this.__renderControl(params); - const ret = new paper.CompoundPath(""); - ret.addChild(rotarymixer_flow); - ret.addChild(rotarymixer_control); - ret.fillColor = params.color; - ret.fillColor!.alpha = 0.5; - - return ret; - } - - __renderFlow(params: { [k: string]: any }) { - const position = params.position; - const radius = params.radius; - const color = params.color; - const rotation = params.rotation; - const valvespacing = params.valveSpacing; - const valvelength = params.valveLength; - const valvewidth = params.valveWidth; - const flowChannelWidth = params.flowChannelWidth; // params["flowChannelWidth"]; - const px = position[0]; - const py = position[1]; - const center = new paper.Point(px, py); - const channellength = radius + valvelength + 2 * valvespacing + flowChannelWidth; // This needs to be a real expression - - const rotarymixer = new paper.CompoundPath(""); - - const innercirc = new paper.Path.Circle(center, radius); - const outercirc = new paper.Path.Circle(center, radius + flowChannelWidth); - - let rotary = outercirc.subtract(innercirc); - - let topleft = new paper.Point(px - valvelength / 2, py - radius - flowChannelWidth / 2 - valvewidth / 2); - const topmiddlerectangle = new paper.Path.Rectangle(topleft, new paper.Size(valvelength, valvewidth)); - rotary = rotary.subtract(topmiddlerectangle); - - topleft = new paper.Point(px + radius + flowChannelWidth / 2 - valvewidth / 2, py - valvelength / 2); - const middlerightrectangle = new paper.Path.Rectangle(topleft, new paper.Size(valvewidth, valvelength)); - rotary = rotary.subtract(middlerightrectangle); - - topleft = new paper.Point(px - valvelength / 2, py + radius + flowChannelWidth / 2 - valvewidth / 2); - const bottommiddlerectangle = new paper.Path.Rectangle(topleft, new paper.Size(valvelength, valvewidth)); - rotary = rotary.subtract(bottommiddlerectangle); - - rotarymixer.addChild(rotary); - - const point1 = new paper.Point(px, py - radius - flowChannelWidth); - const point2 = new paper.Point(px + channellength, py - radius); - let rectangle: paper.Path.Rectangle | paper.PathItem = new paper.Path.Rectangle(point1, point2); - - topleft = new paper.Point(px + radius + flowChannelWidth + valvespacing, py - radius - flowChannelWidth / 2 - valvewidth / 2); - const topleftrectangle = new paper.Path.Rectangle(topleft, new paper.Size(valvelength, valvewidth)); - rectangle = rectangle.subtract(topleftrectangle); - - rectangle = rectangle.subtract(topmiddlerectangle); - - rotarymixer.addChild(rectangle); - - const point3 = new paper.Point(px - channellength, py + radius); - const point4 = new paper.Point(px, py + radius + flowChannelWidth); - let rectangle2: paper.Path.Rectangle | paper.PathItem = new paper.Path.Rectangle(point3, point4); - - topleft = new paper.Point(px - radius - valvespacing - valvelength - flowChannelWidth, py + radius + flowChannelWidth / 2 - valvewidth / 2); - const bottomleftrectangle = new paper.Path.Rectangle(topleft, new paper.Size(valvelength, valvewidth)); - rectangle2 = rectangle2.subtract(bottomleftrectangle); - - rectangle2 = rectangle2.subtract(bottommiddlerectangle); - - rotarymixer.addChild(rectangle2); - - rotarymixer.fillColor = color; - rotarymixer.rotate(rotation, new paper.Point(px, py)); - return rotarymixer; - } - - __renderControl(params: { [k: string]: any }) { - const position = params.position; - const radius = params.radius; - const color = params.color; - const rotation = params.rotation; - const valvespacing = params.valveSpacing; - const valvelength = params.valveLength; - const valvewidth = params.valveWidth; - const flowChannelWidth = params.flowChannelWidth; - const controlChannelWidth = params.controlChannelWidth; // params["flowChannelWidth"]; - const px = position[0]; - const py = position[1]; - - const rotarymixer = new paper.CompoundPath(""); - let topleft = null; - const bottomright = null; - - // Draw top right valve - topleft = new paper.Point(px + radius + flowChannelWidth + valvespacing, py - radius - flowChannelWidth / 2 - valvewidth / 2); - const topleftrectangle = new paper.Path.Rectangle(topleft, new paper.Size(valvelength, valvewidth)); - rotarymixer.addChild(topleftrectangle); - - let topLeft = new paper.Point(px + radius + flowChannelWidth + valvespacing + valvelength / 2 - controlChannelWidth / 2, py - radius - flowChannelWidth / 2 - valvewidth); - let bottomRight = new paper.Point(px + radius + flowChannelWidth + valvespacing + valvelength / 2 + controlChannelWidth / 2, py - radius); - rotarymixer.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // Draw top middle valve - topleft = new paper.Point(px - valvelength / 2, py - radius - flowChannelWidth / 2 - valvewidth / 2); - const topmiddlerectangle = new paper.Path.Rectangle(topleft, new paper.Size(valvelength, valvewidth)); - rotarymixer.addChild(topmiddlerectangle); - - topLeft = new paper.Point(px - controlChannelWidth / 2, py - radius - flowChannelWidth / 2 - valvewidth); - bottomRight = new paper.Point(px + controlChannelWidth / 2, py - radius); - rotarymixer.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // Draw middle right valve - topleft = new paper.Point(px + radius + flowChannelWidth / 2 - valvewidth / 2, py - valvelength / 2); - const middlerightrectangle = new paper.Path.Rectangle(topleft, new paper.Size(valvewidth, valvelength)); - rotarymixer.addChild(middlerightrectangle); - - topLeft = new paper.Point(px + flowChannelWidth / 2 + radius, py - controlChannelWidth / 2); - bottomRight = new paper.Point(px + flowChannelWidth / 2 + radius + valvewidth, py + controlChannelWidth / 2); - rotarymixer.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // Draw Bottom middle valve - topleft = new paper.Point(px - valvelength / 2, py + radius + flowChannelWidth / 2 - valvewidth / 2); - const bottommiddlerectangle = new paper.Path.Rectangle(topleft, new paper.Size(valvelength, valvewidth)); - rotarymixer.addChild(bottommiddlerectangle); - - topLeft = new paper.Point(px - controlChannelWidth / 2, py + radius + flowChannelWidth / 2); - bottomRight = new paper.Point(px + controlChannelWidth / 2, py + radius + flowChannelWidth / 2 + valvewidth); - rotarymixer.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // Draw bottom left valve - topleft = new paper.Point(px - radius - valvespacing - valvelength - flowChannelWidth, py + radius + flowChannelWidth / 2 - valvewidth / 2); - const bottomleftrectangle = new paper.Path.Rectangle(topleft, new paper.Size(valvelength, valvewidth)); - rotarymixer.addChild(bottomleftrectangle); - - topLeft = new paper.Point(px - radius - valvespacing - valvelength - flowChannelWidth / 2 - controlChannelWidth / 2, py + radius + flowChannelWidth / 2); - bottomRight = new paper.Point(px - radius - valvespacing - valvelength - flowChannelWidth / 2 + controlChannelWidth / 2, py + radius + flowChannelWidth / 2 + valvewidth); - rotarymixer.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - rotarymixer.fillColor = color; - rotarymixer.rotate(rotation, new paper.Point(px, py)); - return rotarymixer; - } -} diff --git a/src/app/library/roundedChannel.ts b/src/app/library/roundedChannel.ts deleted file mode 100644 index 9bfc1df7..00000000 --- a/src/app/library/roundedChannel.ts +++ /dev/null @@ -1,100 +0,0 @@ -import Template from "./template"; -import paper from "paper"; - -export default class RoundedChannel extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - start: "Point", - end: "Point" - }; - - this.__heritable = { - channelWidth: "Float", - height: "Float" - }; - - this.__defaults = { - channelWidth: 0.8 * 1000, - height: 250 - }; - - this.__units = { - channelWidth: "μm", - height: "μm" - }; - - this.__minimum = { - channelWidth: 3, - height: 10 - }; - - this.__maximum = { - channelWidth: 2000, - height: 1200 - }; - - this.__featureParams = { - start: "start", - end: "end", - width: "channelWidth" - }; - - this.__targetParams = { - diameter: "channelWidth" - }; - - this.__placementTool = "DragTool"; - - this.__toolParams = { - start: "start", - end: "end" - }; - - this.__renderKeys = ["FLOW"]; - - this.__mint = "ROUNDED CHANNEL"; - - this.__zOffsetKeys = { - FLOW: "height" - }; - - this.__substrateOffset = { - FLOW: "0" - }; - } - - render2D(params: { [k: string]: any }, key: string) { - const start = params.start; - const end = params.end; - const color = params.color; - const width = params.width; - const baseColor = params.baseColor; - const startPoint = new paper.Point(start[0], start[1]); - const endPoint = new paper.Point(end[0], end[1]); - const vec = endPoint.subtract(startPoint); - const rec = new paper.Path.Rectangle({ - size: [vec.length + width, width], - point: start, - radius: width / 2, - fillColor: color, - strokeWidth: 0 - }); - rec.translate(([-width / 2, -width / 2] as unknown) as paper.Point); - rec.rotate(vec.angle, start); - return rec; - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - const position = params.position; - const radius = params.diameter; - const color1 = params.color; - const pos = new paper.Point(position[0], position[1]); - const outerCircle = new paper.Path.Circle(pos, radius); - outerCircle.fillColor = color1; - return outerCircle; - } -} diff --git a/src/app/library/sorter.ts b/src/app/library/sorter.ts deleted file mode 100644 index 244ce910..00000000 --- a/src/app/library/sorter.ts +++ /dev/null @@ -1,374 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class Sorter extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - rotation: "Float", - height: "Float", - inletWidth: "Float", - inletLength: "Float", - electrodeDistance: "Float", - electrodeWidth: "Float", - electrodeLength: "Float", - outletWidth: "Float", - angle: "Float", - wasteWidth: "Float", - outputLength: "Float", - keepWidth: "Float", - pressureWidth: "Float", - pressureSpacing: "Float", - numberofDistributors: "Float", - channelDepth: "Float", - electrodeDepth: "Float", - pressureDepth: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - rotation: 0, - height: 250, - inletWidth: 0.8 * 1000, - inletLength: 4 * 1000, - electrodeDistance: 1 * 1000, - electrodeWidth: 0.7 * 1000, - electrodeLength: 5 * 1000, - outletWidth: 0.8 * 1000, - angle: 45, - wasteWidth: 1.2 * 1000, - outputLength: 4 * 1000, - keepWidth: 2 * 1000, - pressureWidth: 0.4 * 1000, - pressureSpacing: 1.5 * 1000, - numberofDistributors: 5, - channelDepth: 1000, - electrodeDepth: 1000, - pressureDepth: 1000 - }; - - this.__units = { - componentSpacing: "μm", - rotation: "°", - height: "μm", - inletWidth: "μm", - inletLength: "μm", - electrodeDistance: "μm", - electrodeWidth: "μm", - electrodeLength: "μm", - outletWidth: "μm", - angle: "°", - wasteWidth: "μm", - outputLength: "μm", - keepWidth: "μm", - pressureWidth: "μm", - pressureSpacing: "μm", - numberofDistributors: "μm", - channelDepth: "μm", - electrodeDepth: "μm", - pressureDepth: "μm" - }; - - this.__minimum = { - componentSpacing: 0, - rotation: 0, - height: 10, - inletWidth: 0.5 * 1000, - inletLength: 2 * 1000, - electrodeDistance: 0.5 * 1000, - electrodeWidth: 0.5 * 1000, - electrodeLength: 2.5 * 1000, - outletWidth: 0.5 * 1000, - angle: 0, - wasteWidth: 0.5 * 1000, - outputLength: 2 * 1000, - keepWidth: 2 * 1000, - pressureWidth: 0.2 * 1000, - pressureSpacing: 0.5 * 1000, - numberofDistributors: 1, - channelDepth: 1000, - electrodeDepth: 1000, - pressureDepth: 1000 - }; - - this.__maximum = { - componentSpacing: 10000, - rotation: 360, - height: 1200, - inletWidth: 2 * 1000, - inletLength: 6 * 1000, - electrodeDistance: 1.5 * 1000, - electrodeWidth: 1.5 * 1000, - electrodeLength: 7.5 * 1000, - outletWidth: 2 * 1000, - angle: 180, - wasteWidth: 1.5 * 1000, - outputLength: 6 * 1000, - keepWidth: 3.5 * 1000, - pressureWidth: 1 * 1000, - pressureSpacing: 2 * 1000, - numberofDistributors: 10, - channelDepth: 1000, - electrodeDepth: 1000, - pressureDepth: 1000 - }; - - this.__placementTool = "multilayerPositionTool"; - - this.__toolParams = { - cursorPosition: "position" - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - rotation: "rotation", - inletWidth: "inletWidth", - inletLength: "inletLength", - electrodeDistance: "electrodeDistance", - electrodeWidth: "electrodeWidth", - electrodeLength: "electrodeLength", - outletWidth: "outletWidth", - angle: "angle", - wasteWidth: "wasteWidth", - outputLength: "outputLength", - keepWidth: "keepWidth", - pressureWidth: "pressureWidth", - pressureSpacing: "pressureSpacing", - numberofDistributors: "numberofDistributors", - channelDepth: "channelDepth", - electrodeDepth: "electrodeDepth", - pressureDepth: "pressureDepth" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - rotation: "rotation", - inletWidth: "inletWidth", - inletLength: "inletLength", - electrodeDistance: "electrodeDistance", - electrodeWidth: "electrodeWidth", - electrodeLength: "electrodeLength", - outletWidth: "outletWidth", - angle: "angle", - wasteWidth: "wasteWidth", - outputLength: "outputLength", - keepWidth: "keepWidth", - pressureWidth: "pressureWidth", - pressureSpacing: "pressureSpacing", - numberofDistributors: "numberofDistributors", - channelDepth: "channelDepth", - electrodeDepth: "electrodeDepth", - pressureDepth: "pressureDepth" - }; - - this.__renderKeys = ["FLOW", "INTEGRATION"]; - - this.__mint = "DROPLET SORTER"; - - this.__zOffsetKeys = { - FLOW: "height", - INTEGRATION: "electrodeDepth" - }; - - this.__substrateOffset = { - FLOW: "0", - INTEGRATION: "0" - }; - } - - getPorts(params: { [k: string]: any }) { - const inletLength = params.inletLength; - const angle = params.angle; - const outputLength = params.outputLength; - const pressureWidth = params.pressureWidth; - const pressureSpacing = params.pressureSpacing; - const numberofDistributors = params.numberofDistributors; - - const outletLen = ((numberofDistributors + 0.5) * (pressureSpacing + pressureWidth)) / Math.cos(((angle / 2) * Math.PI) / 180); - - const ports = []; - - ports.push(new ComponentPort(-inletLength, 0, "1", LogicalLayerType.FLOW)); - - ports.push( - new ComponentPort( - outletLen * Math.cos(((angle / 2) * Math.PI) / 180) + outputLength, - -((numberofDistributors + 0.5) * (pressureSpacing + pressureWidth) - pressureWidth / 2) * Math.tan(((angle / 2) * Math.PI) / 180), - "2", - LogicalLayerType.FLOW - ) - ); - - ports.push( - new ComponentPort( - outletLen * Math.cos(((angle / 2) * Math.PI) / 180) + outputLength, - ((numberofDistributors + 0.5) * (pressureSpacing + pressureWidth) - pressureWidth / 2) * Math.tan(((angle / 2) * Math.PI) / 180), - "3", - LogicalLayerType.FLOW - ) - ); - - return ports; - } - - __renderFlow(params: { [k: string]: any }) { - const rotation = params.rotation; - const x = params.position[0]; - const y = params.position[1]; - const color = params.color; - const inletWidth = params.inletWidth; - const inletLength = params.inletLength; - const outletWidth = params.outletWidth; - const angle = params.angle; - const wasteWidth = params.wasteWidth; - const outputLength = params.outputLength; - const keepWidth = params.keepWidth; - const pressureWidth = params.pressureWidth; - const pressureSpacing = params.pressureSpacing; - const numberofDistributors = params.numberofDistributors; - const serp = new paper.CompoundPath(""); - - // pressure distributors - for (let i = 0; i < numberofDistributors; i++) { - const newRightX = (i + 1.5) * (pressureSpacing + pressureWidth); - - const newLeftX = newRightX - pressureWidth; - - const pHeight = (newRightX - pressureWidth / 2) * Math.tan(((angle / 2) * Math.PI) / 180); - // upper - let topLeft = new paper.Point(x + newLeftX, y - pHeight); - let bottomRight = new paper.Point(x + newRightX, y); - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // lower - topLeft = new paper.Point(x + newLeftX, y + pHeight); - bottomRight = new paper.Point(x + newRightX, y); - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - } - - const outletLen = ((numberofDistributors + 0.5) * (pressureSpacing + pressureWidth)) / Math.cos(((angle / 2) * Math.PI) / 180); - let topLeft = new paper.Point(x, y - outletWidth / 2); - let bottomRight = new paper.Point(x + outletLen, y + outletWidth / 2); - - // upper outlet - let outlet = new paper.Path.Rectangle(topLeft, bottomRight); - outlet.rotate(-angle / 2, new paper.Point(x, y)); - serp.addChild(outlet); - - // lower outlet - outlet = new paper.Path.Rectangle(topLeft, bottomRight); - outlet.rotate(angle / 2, new paper.Point(x, y)); - serp.addChild(outlet); - - // inlet - topLeft = new paper.Point(x - inletLength, y - inletWidth / 2); - bottomRight = new paper.Point(x, y + inletWidth / 2); - - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // waste - topLeft = new paper.Point( - x + outletLen * Math.cos(((angle / 2) * Math.PI) / 180), - y - ((numberofDistributors + 0.5) * (pressureSpacing + pressureWidth) - pressureWidth / 2) * Math.tan(((angle / 2) * Math.PI) / 180) - wasteWidth / 2 - ); - bottomRight = new paper.Point( - x + outletLen * Math.cos(((angle / 2) * Math.PI) / 180) + outputLength, - y - ((numberofDistributors + 0.5) * (pressureSpacing + pressureWidth) - pressureWidth / 2) * Math.tan(((angle / 2) * Math.PI) / 180) + wasteWidth / 2 - ); - - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // keep - topLeft = new paper.Point( - x + outletLen * Math.cos(((angle / 2) * Math.PI) / 180), - y + ((numberofDistributors + 0.5) * (pressureSpacing + pressureWidth) - pressureWidth / 2) * Math.tan(((angle / 2) * Math.PI) / 180) - keepWidth / 2 - ); - bottomRight = new paper.Point( - x + outletLen * Math.cos(((angle / 2) * Math.PI) / 180) + outputLength, - y + ((numberofDistributors + 0.5) * (pressureSpacing + pressureWidth) - pressureWidth / 2) * Math.tan(((angle / 2) * Math.PI) / 180) + keepWidth / 2 - ); - - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - serp.rotate(rotation, new paper.Point(x, y)); - - serp.fillColor = color; - return serp; - } - - __renderIntegrate(params: { [k: string]: any }) { - const rotation = params.rotation; - const x = params.position[0]; - const y = params.position[1]; - const color = params.color; - const electrodeDistance = params.electrodeDistance; - const electrodeWidth = params.electrodeWidth; - const electrodeLength = params.electrodeLength; - const angle = params.angle; - const serp = new paper.CompoundPath(""); - - // middle electrode - let topLeft = new paper.Point(x - electrodeWidth / 2, y + electrodeDistance); - let bottomRight = new paper.Point(x + electrodeWidth / 2, y + electrodeDistance + electrodeLength); - - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // left electrode - topLeft = new paper.Point(x - electrodeWidth / 2 - 2 * electrodeWidth, y + electrodeDistance); - bottomRight = new paper.Point(x + electrodeWidth / 2 - 2 * electrodeWidth, y + electrodeDistance + electrodeLength); - - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // right electrode - topLeft = new paper.Point(x - electrodeWidth / 2 + 2 * electrodeWidth, y + electrodeDistance + 2 * electrodeWidth * Math.tan(((angle / 2) * Math.PI) / 180)); - bottomRight = new paper.Point( - x + electrodeWidth / 2 + 2 * electrodeWidth, - y + electrodeDistance + 2 * electrodeWidth * Math.tan(((angle / 2) * Math.PI) / 180) + electrodeLength - ); - - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - serp.rotate(rotation, new paper.Point(x, y)); - - serp.fillColor = color; - return serp; - } - - // render2DTarget(key, params) { - // const serp = this.render2D(params, key); - - // serp.fillColor.alpha = 0.5; - // return serp; - // } - - render2D(params: { [k: string]: any }, key = "FLOW") { - if (key === "FLOW") { - return this.__renderFlow(params); - } else if (key === "INTEGRATION") { - return this.__renderIntegrate(params); - } - throw new Error("Unknown render key found in DROPLET SORTER: " + key); - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - const ret = new paper.CompoundPath(""); - const flow = this.render2D(params, "FLOW"); - const integrate = this.render2D(params, "INTEGRATION"); - ret.addChild(integrate); - ret.addChild(flow); - ret.fillColor = params.color; - ret.fillColor!.alpha = 0.5; - return ret; - } -} diff --git a/src/app/library/splitter.ts b/src/app/library/splitter.ts deleted file mode 100644 index 60c9980c..00000000 --- a/src/app/library/splitter.ts +++ /dev/null @@ -1,188 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class Splitter extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - rotation: "Float", - height: "Float", - inletWidth: "Float", - inletLength: "Float", - outletWidth1: "Float", - outletLength1: "Float", - outletWidth2: "Float", - outletLength2: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - rotation: 0, - height: 250, - inletWidth: 2 * 1000, - inletLength: 6 * 1000, - outletWidth1: 1 * 1000, - outletLength1: 3 * 1000, - outletWidth2: 2 * 1000, - outletLength2: 3 * 1000 - }; - - this.__units = { - componentSpacing: "μm", - rotation: "°", - height: "μm", - inletWidth: "μm", - inletLength: "μm", - outletWidth1: "μm", - outletLength1: "μm", - outletWidth2: "μm", - outletLength2: "μm" - }; - - this.__minimum = { - componentSpacing: 0, - rotation: 0, - height: 10, - inletWidth: 1 * 1000, - inletLength: 3 * 1000, - outletWidth1: 0.5 * 1000, - outletLength1: 2 * 1000, - outletWidth2: 0.5 * 1000, - outletLength2: 2 * 1000 - }; - - this.__maximum = { - componentSpacing: 10000, - rotation: 360, - height: 1200, - inletWidth: 3 * 1000, - inletLength: 8 * 1000, - outletWidth1: 3 * 1000, - outletLength1: 5 * 1000, - outletWidth2: 3 * 1000, - outletLength2: 5 * 1000 - }; - - this.__placementTool = "componentPositionTool"; - - this.__toolParams = { - cursorPosition: "position" - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - rotation: "rotation", - height: "height", - inletWidth: "inletWidth", - inletLength: "inletLength", - outletWidth1: "outletWidth1", - outletLength1: "outletLength1", - outletWidth2: "outletWidth2", - outletLength2: "outletLength2" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - rotation: "rotation", - height: "height", - inletWidth: "inletWidth", - inletLength: "inletLength", - outletWidth1: "outletWidth1", - outletLength1: "outletLength1", - outletWidth2: "outletWidth2", - outletLength2: "outletLength2" - }; - - this.__renderKeys = ["FLOW"]; - - this.__mint = "DROPLET SPLITTER"; - - this.__zOffsetKeys = { - FLOW: "height" - }; - - this.__substrateOffset = { - FLOW: "0" - }; - } - - getPorts(params: { [k: string]: any }) { - const inletWidth = params.inletWidth; - const inletLength = params.inletLength; - const outletWidth1 = params.outletWidth1; - const outletLength1 = params.outletLength1; - const outletWidth2 = params.outletWidth2; - const outletLength2 = params.outletLength2; - - const ports = []; - - // inlet - ports.push(new ComponentPort(0, 0, "1", LogicalLayerType.FLOW)); - - // outlet 1 - ports.push(new ComponentPort(inletLength - outletWidth1 / 2, -inletWidth / 2 - outletLength1, "2", LogicalLayerType.FLOW)); - - // outlet 2 - ports.push(new ComponentPort(inletLength - outletWidth2 / 2, inletWidth / 2 + outletLength2, "3", LogicalLayerType.FLOW)); - - return ports; - } - - render2D(params: { [k: string]: any }, key: string) { - const rotation = params.rotation; - const x = params.position[0]; - const y = params.position[1]; - const color = params.color; - const inletWidth = params.inletWidth; - const inletLength = params.inletLength; - const outletWidth1 = params.outletWidth1; - const outletLength1 = params.outletLength1; - const outletWidth2 = params.outletWidth2; - const outletLength2 = params.outletLength2; - - const serp = new paper.CompoundPath(""); - - // inlet - let topLeft = new paper.Point(x, y - inletWidth / 2); - let bottomRight = new paper.Point(x + inletLength, y + inletWidth / 2); - - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // outlet 1 - topLeft = new paper.Point(x + inletLength - outletWidth1, y - inletWidth / 2 - outletLength1); - bottomRight = new paper.Point(x + inletLength, y - inletWidth / 2); - - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // outlet 2 - topLeft = new paper.Point(x + inletLength - outletWidth2, y + inletWidth / 2); - bottomRight = new paper.Point(x + inletLength, y + inletWidth / 2 + outletLength2); - - serp.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - serp.rotate(rotation, new paper.Point(x, y)); - - serp.fillColor = color; - return serp; - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - if (key === null) { - key = this.__renderKeys[0]; - } - const serp = this.render2D(params, key); - serp.fillColor!.alpha = 0.5; - return serp; - } -} diff --git a/src/app/library/template.ts b/src/app/library/template.ts deleted file mode 100755 index c736a4b3..00000000 --- a/src/app/library/template.ts +++ /dev/null @@ -1,446 +0,0 @@ -import ComponentPort from "../core/componentPort"; -import { ToolPaperObject } from "../core/init"; -import paper from "paper"; -//import { ManufacturingInfo } from "../manufacturing/ManufacturingInfo"; -import { LogicalLayerType } from "../core/init"; -import {PRIMITIVES_SERVER} from "../../componentAPI"; -export enum PositionToolType { - FEATURE_POSITION_TOOL = "positionTool", - COMPONENT_POSITION_TOOL = "componentPositionTool", - MULTILAYER_POSITION_TOOL = "multilayerPositionTool", - VALVE_INSERTION_TOOL = "valveInsertionTool" -} - -export default class Template { - protected __unique: { [key: string]: string } | null = null; - protected __heritable: { [key: string]: string } | null = null; - protected __defaults: { [key: string]: number } | null = null; - protected __minimum: { [key: string]: number } | null = null; - protected __maximum: { [key: string]: number } | null = null; - protected __units: { [key: string]: string } | null = null; - protected __placementTool: string | null = null; - protected __toolParams: { [key: string]: string } | null = null; // { position: "position" }; - protected __featureParams: { [key: string]: string } | null = null; - protected __targetParams: { [key: string]: string } | null = null; - protected __mint: string | null = null; - protected __renderKeys: Array = ["FLOW"]; - protected _previewImage: string = ""; - protected __zOffsetKeys: { [key: string]: string } | null = null; - protected __substrateOffset: { [key: string]: string } | null = null; - protected __childFeatureMacros: Array = []; // Store all the macro names - - /** - *Creates an instance of Template. - * @memberof Template - */ - constructor() { - this.__setupDefinitions(); - } - - /** - * Returns the mint definition for the component definition - * - * @readonly - * @type {string} - * @memberof Template - */ - get mint(): string { - if (this.__mint === null) { - throw new Error("User needs to provide unique MINT string for component type"); - } - return this.__mint; - } - - /** - * Returns the z-offset-key for the given layer type - * - * @param {string} - * @memberof Template - */ - zOffsetKey(key: string): string { - if (this.__zOffsetKeys === null) { - throw new Error("zOffsetKey cannot be null instantiate in the __setupDefinitions"); - } else if (this.__zOffsetKeys.hasOwnProperty(key)) { - return this.__zOffsetKeys[key]; - } else { - throw new Error("zOffsetKey does not contain key " + key); - } - } - - /** - * Returns the z-offset-key for the given layer type - * - * @param {string} - * @memberof Template - */ - substrateOffset(key: string): string { - if (this.__substrateOffset === null) { - throw new Error("substrateOffset cannot be null instantiate in the __setupDefinitions"); - } else if (this.__substrateOffset.hasOwnProperty(key)) { - return this.__substrateOffset[key]; - } else { - throw new Error("substrateOffset does not contain key " + key); - } - } - - /** - * TODO - Remove this thing's dependency - */ - get featureParams(): { [key: string]: string } { - if (this.__featureParams === null) { - throw new Error("featureParams cannot be null instantiate in the __setupDefinitions"); - } - - return this.__featureParams; - } - - /** - * TODO - Remove this thing's dependency - */ - get targetParams(): { [key: string]: string } { - if (this.__targetParams === null) { - throw new Error("targetParams cannot be null instantiate in the __setupDefinitions"); - } - - return this.__targetParams; - } - - /** - * Returns the placement tool for the component/feature - * - * @readonly - * @type {string} - * @memberof Template - */ - get placementTool(): string { - if (this.__placementTool === null) { - throw new Error("placementtool cannot be null instantiate in the __setupDefinitions"); - } - - return this.__placementTool; - } - - /** - * Returns the tool params for the component - * - * @readonly - * @type {{ [key: string]: string }} - * @memberof Template - */ - get toolParams(): { [key: string]: string } { - if (this.__toolParams === null) { - throw new Error("toolparams cannot be null instantiate in the __setupDefinitions"); - } - - return this.__toolParams; - } - - /** - * Returns the default value for the component params - * - * @readonly - * @type {{ [key: string]: number }} - * @memberof Template - */ - get defaults(): { [key: string]: number } { - if (this.__defaults === null) { - throw new Error("defaults cannot be null instantiate in the __setupDefinitions"); - } - - return this.__defaults; - } - - /** - * Returns the min value for the component params - * - * @readonly - * @type {{ [key: string]: number }} - * @memberof Template - */ - get minimum(): { [key: string]: number } { - if (this.__minimum === null) { - throw new Error("minimum cannot be null instantiate in the __setupDefinitions"); - } - - return this.__minimum; - } - - /** - * Returns the max value for the component params - * - * @readonly - * @type {{ [key: string]: number }} - * @memberof Template - */ - get maximum(): { [key: string]: number } { - if (this.__maximum === null) { - throw new Error("maximum cannot be null instantiate in the __setupDefinitions"); - } - - return this.__maximum; - } - - /** - * Returns the units for the component params - * - * @readonly - * @type {{ [key: string]: string }} - * @memberof Template - */ - get units(): { [key: string]: string } { - if (this.__units === null) { - throw new Error("units cannot be null instantiate in the __setupDefinitions"); - } - - return this.__units; - } - - /** - * Returns the unique params for the component definition - * - * @readonly - * @type {{ [key: string]: string }} - * @memberof Template - */ - get unique(): { [key: string]: string } { - if (this.__unique === null) { - throw new Error("unique cannot be null instantiate in the __setupDefinitions"); - } - - return this.__unique; - } - - /** - * Returns the heritable properties for the component definition - * - * @readonly - * @type {{ [key: string]: string }} - * @memberof Template - */ - get heritable(): { [key: string]: string } { - if (this.__heritable === null) { - throw new Error("Heritable cannot be null instantiate in the __setupDefinitions"); - } - return this.__heritable; - } - - /** - * Returns the renderkeys for the component definition - * - * @readonly - * @type {Array} - * @memberof Template - */ - get renderKeys(): Array { - if (this.__renderKeys === null) { - throw new Error("renderKeys cannot be null instantiate in the __setupDefinitions"); - } - - return this.__renderKeys; - } - - /** - * Returns the preview link for the component - * - * @readonly - * @type {string} - * @memberof Template - */ - get previewImage(): string { - return this._previewImage; - } - get childFeatureMacros(): Array { - return this.__childFeatureMacros; - } - - - /** - * Override this method to setup the definitions for the component - * - * @memberof Template - */ - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - height: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - height: 250 - }; - - this.__units = { - componentSpacing: "μm", - height: "μm" - }; - - this.__minimum = { - componentSpacing: 0, - height: 10 - }; - - this.__maximum = { - componentSpacing: 10000, - height: 1200 - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position" - }; - - this.__targetParams = { - }; - - this.__placementTool = "componentPositionTool"; - - this.__toolParams = { - position: "position" - }; - - this.__renderKeys = ["FLOW"]; - - this.__mint = "TEMPLATE"; - - this.__zOffsetKeys = { - FLOW: "height" - }; - - this.__substrateOffset = { - FLOW: "0" - }; - - /* - Check https://github.com/CIDARLAB/3DuF/wiki/Adding-new-components-v2 for more example data - */ - //throw new Error("User needs to provide method for component definition, look at examples"); - } - - /* - * Replacing /src/app/view/render2D/primitiveSets2D/basic2D - */ - - /** - * Returns the paperjs render for a given key (can be control/flow or anything user defined key that for future - * compatibility. - * @param key - */ - render2D(params: { [key: string]: any }, key: string): ToolPaperObject { - console.error("Default component template being used. User needs to provide method for component definition, look at examples"); - const x = params.position[0]; - const y = params.position[1]; - - const rect = new paper.Path.Rectangle(new paper.Point(x - 100, y - 100), new paper.Size(5000, 5000)); - rect.fillColor = params.color; - return rect; - } - - - /** - * Returns the render target for the component - * - * @param {string} key - * @param {{ [key: string]: any }} params - * @returns {ToolPaperObject} - * @memberof Template - */ - render2DTarget(key: string | null, params: { [key: string]: any }): ToolPaperObject { - throw new Error("User needs to provide method for component definition, look at examples"); - } - - /** - * Returns the ports for the component definition - * @param params - */ - getPorts(params: { [key: string]: any }): Array { - console.error("User needs to provide method for component definition, look at examples"); - const ports = []; - ports.push(new ComponentPort(0, 0, "1", LogicalLayerType.FLOW)); - return ports; - } - - /** - * Returns the bounds for component for given params. This assummes that the mint definiton, - * render2D is implemented for the given defintion. - * - * @param {{ [key: string]: any }} params - * @returns {paper.Rectangle} - * @memberof Template - */ - getBounds(params: { [key: string]: any }): paper.Rectangle{ - const renderkeys = this.renderKeys; - const features: Array = []; - for (let i = 0; i < renderkeys.length; i++) { - const feature = this.render2D(params, renderkeys[i]); - if(feature instanceof paper.PointText){ - continue; - } - features.push(feature.bounds); - } - - const unitedBounds = features.reduce((bbox, item): paper.Rectangle => { - if (item === null || item instanceof paper.PointText) { - return bbox; - }else{ - return !bbox ? item : bbox.unite(item); - } - }); - if (unitedBounds) { - return unitedBounds; - } else { - return new paper.Rectangle(0, 0, 0, 0); - } - } - - /** - * Returns the dimensions for the component for given params. - * - * @param {{ [key: string]: any }} params - * @returns {{ xspan: any; yspan: any }} - * @memberof Template - */ - getDimensions(params: { [key: string]: any }): { xspan: any; yspan: any } { - // TODO - Figure out a workaround for this - if (PRIMITIVES_SERVER) { - paper.setup(new paper.Size([64000, 48000])); - } - - params.position = [0, 0]; - - const unitedBounds = this.getBounds(params); - if (unitedBounds === null) { - throw new Error("No bounds found for component"); - } - const xspan = unitedBounds.width; - const yspan = unitedBounds.height; - // console.log("Dimensions:",xspan, yspan); - return { xspan: xspan, yspan: yspan }; - } - - /** - * Returns the drawing offset for the component for given params. This assummes - * that the mint definiton, and the getBounds methd works correctly - * - * @param {{ [key: string]: any }} params - * @returns - * @memberof Template - */ - getDrawOffset(params: { [key: string]: any }) { - params.position = [0, 0]; - params.rotation = 0; - const position = params.position; - const positionUnitedBounds = this.getBounds(params); - // console.log(positionUnitedBounds.topLeft, position); - if (positionUnitedBounds === null) { - throw new Error("unitedBounds is null"); - } - const x_new = position[0] - positionUnitedBounds.topLeft.x; - const y_new = position[1] - positionUnitedBounds.topLeft.y; - return [x_new, y_new]; - } -} diff --git a/src/app/library/text.ts b/src/app/library/text.ts deleted file mode 100644 index 464f7ee0..00000000 --- a/src/app/library/text.ts +++ /dev/null @@ -1,94 +0,0 @@ -import Template from "./template"; -import paper from "paper"; - -export default class Text extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - text: "String", - height: "Float", - fontSize: "Float" - }; - - this.__defaults = { - fontSize: 10000 / 3, - height: 250 - }; - - this.__units = { - fontSize: "μm", - height: "μm" - }; - - this.__minimum = { - fontSize: 10000 / 3, - height: 1 - }; - - this.__maximum = { - fontSize: 10000 / 3, - height: 10000 - }; - - this.__toolParams = { - position: "position" - }; - - this.__featureParams = { - position: "position", - text: "text", - fontSize: "fontSize", - height: "height" - }; - - this.__targetParams = { - text: "text", - fontSize: "fontSize", - height: "height" - }; - - this.__placementTool = "PositionTool"; - - this.__renderKeys = ["FLOW"]; - - this.__mint = "TEXT"; - - this.__zOffsetKeys = { - FLOW: "height" - }; - - this.__substrateOffset = { - FLOW: "0" - }; - } - - render2D(params: { [k: string]: any }, key: string) { - // Regardless of the key... - const position = params.position; - const text = params.text; - const color = params.color; - const rendered = new paper.PointText(new paper.Point(position[0], position[1])); - rendered.justification = "center"; - rendered.fillColor = color; - /// rendered.content = feature.getText(); - rendered.content = text; - rendered.fontSize = 10000 / 3; - return rendered; - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - if (key === null) { - key = this.__renderKeys[0]; - } - const render = this.render2D(params, key); - render.fillColor!.alpha = 0.5; - return render; - } -} diff --git a/src/app/library/thermoCycler.ts b/src/app/library/thermoCycler.ts deleted file mode 100644 index f99571de..00000000 --- a/src/app/library/thermoCycler.ts +++ /dev/null @@ -1,151 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class thermoCycler extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - this.__heritable = { - componentSpacing: "Float", - rotation: "Float", - width: "Float", - length: "Float", - height: "Float", - temperature: "Float" - }; - this.__defaults = { - componentSpacing: 1000, - rotation: 0, - width: 20 * 1000, - length: 40 * 1000, - height: 5 * 1000, - temperature: 0.03 * 1000 - }; - this.__units = { - componentSpacing: "μm", - rotation: "°", - width: "μm", - length: "μm", - height: "μm", - temperature: "°C" - }; - this.__minimum = { - componentSpacing: 0, - rotation: 0, - width: 10 * 1000, - length: 10 * 1000, - height: 1.25 * 1000, - temperature: 0 * 1000 - }; - this.__maximum = { - componentSpacing: 10000, - rotation: 90, - width: 60 * 1000, - length: 60 * 1000, - height: 10 * 1000, - temperature: 0.1 * 1000 - }; - this.__placementTool = "multilayerPositionTool"; - this.__toolParams = { - position: "position" - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - rotation: "rotation", - length: "length", - width: "width", - temperature: "temperature" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - rotation: "rotation", - length: "length", - width: "width", - temperature: "temperature" - }; - - this.__renderKeys = ["FLOW"]; - - this.__mint = "THERMO CYCLER"; - - this.__zOffsetKeys = { - FLOW: "height" - }; - - this.__substrateOffset = { - FLOW: "0" - }; - } - - render2D(params: { [k: string]: any }, key: string) { - const position = params.position; - const rotation = params.rotation; - const px = position[0]; - const py = position[1]; - const l = params.length; - const w = params.width; - const color = params.color; - const startX = px - w / 2; - const startY = py - l / 2; - const endX = px + w / 2; - const endY = py + l / 2; - const startPoint = new paper.Point(startX, startY); - const endPoint = new paper.Point(endX, endY); - const rendered = new paper.CompoundPath(""); - const cirrad = l / 4; - const centerr = new paper.Point(px - w, py - l); - - const rec = new paper.Path.Rectangle({ - from: startPoint, - to: endPoint, - radius: 0, - fillColor: color, - strokeWidth: 0 - }); - rendered.addChild(rec); - - // let cir = new paper.Path.Circle({ - // center: centerr, - // radius: cirrad, - // fillColor: 'black' - // }) - // rendered.addChild(cir); - - rendered.fillColor = color; - // cir.fillColor = 'black'; - // rec.addChild(cir) - rendered.rotate(rotation, new paper.Point(px, py)); - return rendered; - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - if (key === null) { - key = this.__renderKeys[0]; - } - const render = this.render2D(params, key); - render.fillColor!.alpha = 0.5; - return render; - } - - getPorts(params: { [k: string]: any }) { - const l = params.length; - const w = params.width; - - const ports = []; - - ports.push(new ComponentPort(-w / 2, -l / 6, "1", LogicalLayerType.CONTROL)); - ports.push(new ComponentPort(-w / 2, l / 6, "2", LogicalLayerType.CONTROL)); - - return ports; - } -} diff --git a/src/app/library/threeDMixer.ts b/src/app/library/threeDMixer.ts deleted file mode 100644 index 010a0c6e..00000000 --- a/src/app/library/threeDMixer.ts +++ /dev/null @@ -1,183 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class ThreeDMixer extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - bendSpacing: "Float", - numberOfBends: "Float", - channelWidth: "Float", - bendLength: "Float", - rotation: "Float", - height: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - channelWidth: 0.8 * 1000, - bendSpacing: 1.23 * 1000, - numberOfBends: 1, - rotation: 0, - bendLength: 2.46 * 1000, - height: 250 - }; - - this.__units = { - componentSpacing: "μm", - bendSpacing: "μm", - numberOfBends: "", - channelWidth: "μm", - bendLength: "μm", - rotation: "°", - height: "μm" - }; - - this.__minimum = { - componentSpacing: 0, - channelWidth: 10, - bendSpacing: 10, - numberOfBends: 1, - rotation: 0, - bendLength: 10, - height: 10 - }; - - this.__maximum = { - componentSpacing: 10000, - channelWidth: 2000, - bendSpacing: 6000, - numberOfBends: 20, - rotation: 360, - bendLength: 12 * 1000, - height: 1200 - }; - - this.__placementTool = "multilayerPositionTool"; - - this.__toolParams = { - cursorPosition: "position" - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - channelWidth: "channelWidth", - bendSpacing: "bendSpacing", - numberOfBends: "numberOfBends", - rotation: "rotation", - bendLength: "bendLength" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - channelWidth: "channelWidth", - bendSpacing: "bendSpacing", - numberOfBends: "numberOfBends", - rotation: "rotation", - bendLength: "bendLength" - }; - - this.__renderKeys = ["FLOW", "CONTROL"]; - - this.__mint = "MIXER3D"; - - this.__zOffsetKeys = { - FLOW: "height", - CONTROL: "height" - }; - - this.__substrateOffset = { - FLOW: "0", - CONTROL: "+1" - }; - } - - getPorts(params: { [k: string]: any }) { - const channelWidth = params.channelWidth; - const bendLength = params.bendLength; - const bendSpacing = params.bendSpacing; - const rotation = params.rotation; - const numberOfBends = params.numberOfBends; - - const ports = []; - - ports.push(new ComponentPort(bendLength / 2 + channelWidth, 0, "1", LogicalLayerType.FLOW)); - - ports.push(new ComponentPort(bendLength / 2 + channelWidth, (2 * numberOfBends + 1) * channelWidth + 2 * numberOfBends * bendSpacing, "2", LogicalLayerType.FLOW)); - - return ports; - } - - render2D(params: { [k: string]: any }, key: string) { - const channelWidth = params.channelWidth; - const bendLength = params.bendLength; - const bendSpacing = params.bendSpacing; - const rotation = params.rotation; - const numBends = params.numberOfBends; - const x = params.position[0]; - const y = params.position[1]; - const color = params.color; - const segHalf = bendLength / 2 + channelWidth; - const segLength = bendLength + 2 * channelWidth; - const segBend = bendSpacing + 2 * channelWidth; - const vRepeat = 2 * bendSpacing + 2 * channelWidth; - const vOffset = bendSpacing + channelWidth; - const hOffset = bendLength / 2 + channelWidth / 2; - const serp = new paper.CompoundPath(""); - - if (key === "FLOW") { - // draw first segment - serp.addChild(new paper.Path.Rectangle(new paper.Rectangle(x, y, segHalf + channelWidth / 2, channelWidth))); - for (let i = 0; i < numBends; i++) { - serp.addChild(new paper.Path.Rectangle(new paper.Rectangle(x, y + vRepeat * i, channelWidth, segBend))); - // serp.addChild(new paper.Path.Rectangle(x, y + vOffset + vRepeat * i, segLength, channelWidth)); - serp.addChild(new paper.Path.Rectangle(new paper.Rectangle(x + channelWidth + bendLength, y + vOffset + vRepeat * i, channelWidth, segBend))); - if (i === numBends - 1) { - // draw half segment to close - serp.addChild(new paper.Path.Rectangle(new paper.Rectangle(x + hOffset, y + vRepeat * (i + 1), segHalf, channelWidth))); - } else { - // draw full segment - serp.addChild(new paper.Path.Rectangle(new paper.Rectangle(x, y + vRepeat * (i + 1), segLength, channelWidth))); - } - } - } else { - // draw first segment - // serp.addChild(new paper.Path.Rectangle(x, y, segHalf + channelWidth / 2, channelWidth)); - for (let i = 0; i < numBends; i++) { - // serp.addChild(new paper.Path.Rectangle(x, y + vRepeat * i, channelWidth, segBend)); - serp.addChild(new paper.Path.Rectangle(new paper.Rectangle(x, y + vOffset + vRepeat * i, segLength, channelWidth))); - // serp.addChild(new paper.Path.Rectangle(x + channelWidth + bendLength, y + vOffset + vRepeat * i, channelWidth, segBend)); - // if (i === numBends - 1) {//draw half segment to close - // serp.addChild(new paper.Path.Rectangle(x + hOffset, y + vRepeat * (i + 1), segHalf, channelWidth)); - // } else {//draw full segment - // serp.addChild(new paper.Path.Rectangle(x, y + vRepeat * (i + 1), segLength, channelWidth)); - // } - } - } - - serp.fillColor = color; - serp.rotate(rotation, new paper.Point(x, y)); - return serp; - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - if (key === null) { - key = this.__renderKeys[0]; - } - const serp = this.render2D(params, key); - serp.fillColor = params.color; - serp.fillColor!.alpha = 0.5; - return serp; - } -} diff --git a/src/app/library/threeDMux.ts b/src/app/library/threeDMux.ts deleted file mode 100644 index 8115c1cd..00000000 --- a/src/app/library/threeDMux.ts +++ /dev/null @@ -1,544 +0,0 @@ -import Template from "./template"; -import paper, { CompoundPath } from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class ThreeDMux extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - in: "Integer", - out: "Integer", - rotation: "Float", - valveRadius: "Float", - height: "Float", - gap: "Float", - width: "Float", - length: "Float", - valveSpacing: "Float", - channelWidth: "Float", - controlChannelWidth: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - in: 1, - out: 8, - rotation: 0, - valveRadius: 1.2 * 1000, - height: 0.8 * 1000, - gap: 0.6 * 1000, - width: 100, - length: 100, - valveSpacing: 0.6 * 1000, - channelWidth: 500, - controlChannelWidth: 0.6 * 1000 - }; - - this.__units = { - componentSpacing: "μm", - in: "", - out: "", - rotation: "°", - valveRadius: "μm", - height: "μm", - gap: "μm", - width: "μm", - length: "μm", - valveSpacing: "μm", - channelWidth: "μm", - controlChannelWidth: "μm" - }; - - this.__minimum = { - componentSpacing: 0, - in: 1, - out: 2, - rotation: 0, - valveRadius: 0.1 * 100, - height: 0.1 * 100, - gap: 0.5 * 10, - width: 100, - length: 100, - valveSpacing: 0.1 * 1000, - channelWidth: 25, - controlChannelWidth: 10 - }; - - this.__maximum = { - componentSpacing: 10000, - in: 1, - out: 128, - rotation: 360, - valveRadius: 0.2 * 10000, - height: 1.2 * 1000, - gap: 0.1 * 10000, - width: 100, - length: 100, - valveSpacing: 0.1 * 10000, - channelWidth: 25e3, - controlChannelWidth: 1000 - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - in: "in", - out: "out", - position: "position", - rotation: "rotation", - radius1: "valveRadius", - radius2: "valveRadius", - valveRadius: "valveRadius", - gap: "gap", - width: "width", - length: "length", - valveSpacing: "valveSpacing", - channelWidth: "channelWidth", - controlChannelWidth: "controlChannelWidth" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - in: "in", - out: "out", - position: "position", - rotation: "rotation", - radius1: "valveRadius", - radius2: "valveRadius", - valveRadius: "valveRadius", - gap: "gap", - width: "width", - length: "length", - valveSpacing: "valveSpacing", - channelWidth: "channelWidth", - controlChannelWidth: "controlChannelWidth" - }; - - this.__placementTool = "multilayerPositionTool"; - - this.__toolParams = { - position: "position" - }; - - this.__renderKeys = ["FLOW", "CONTROL", "INVERSE"]; - - this.__mint = "MUX3D"; - - this.__zOffsetKeys = { - FLOW: "height", - CONTROL: "height", - INVERSE: "height" - }; - - this.__substrateOffset = { - FLOW: "0", - CONTROL: "+1", - INVERSE: "0" - }; - } - - render2D(params: { [k: string]: any }, key: string) { - if (key === "FLOW") { - return this.__drawFlow(params); - } else if (key === "CONTROL") { - return this.__drawControl(params); - } else if (key === "INVERSE") { - return this.__drawInverse(params); - }else{ - throw new Error("Unknown key threedmux: " + key); - } - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - const ret = new paper.CompoundPath(""); - const flow = this.render2D(params, "FLOW"); - const control = this.render2D(params, "CONTROL"); - ret.addChild((control as unknown) as paper.CompoundPath); - ret.addChild((flow as unknown) as paper.CompoundPath); - ret.fillColor = params.color; - ret.fillColor!.alpha = 0.5; - return ret; - } - - getPorts(params: { [k: string]: any }) { - const ins = params.in; - const outs = params.out; - let N; - const channelWidth = params.channelWidth; - let rotation = params.rotation; - - if (ins < outs) { - N = outs; - } else { - N = ins; - rotation += 180; - } - - const horizontal_length = N * 4000; - const vertical_length = N * 3000; - const ports = []; - - for (let i = 0; i < N; i++) { - const xpos = i * (horizontal_length / (N - 1)); - ports.push(new ComponentPort(xpos, 0, (i + 1).toString(), LogicalLayerType.FLOW)); - } - - ports.push(new ComponentPort(horizontal_length / 2, vertical_length + N * 1000, (N + 1).toString(), LogicalLayerType.FLOW)); - const bottomlinelength = N * 4000; // modify, so it depends on the input N - const vertlinelength = N * 3000; // same as above - - const leftInput = -N * 1000; - const rightInput = bottomlinelength + N * 1000; - let indexN = N; - const valvenum = Math.log(N) / Math.log(2); - const vertholder = vertlinelength / (2 * valvenum); - - let count = N + 2; - - for (let i = 0; i < 2 * valvenum; i++) { - // left side - if (i % 2 === 0) { - indexN /= 2; - const cur_ind = N - indexN - 1; - // let leftsideLeft = new paper.Point(leftInput, vertholder + (i) * vertlinelength/(2*valvenum + 2) - channelWidth/2); - ports.push(new ComponentPort(leftInput, vertholder + (i * vertlinelength) / (2 * valvenum + 2), count.toString(), LogicalLayerType.CONTROL)); - console.log(count); - count++; - } - // right side - else { - ports.push(new ComponentPort(rightInput, vertholder + (i * vertlinelength) / (2 * valvenum + 2), count.toString(), LogicalLayerType.CONTROL)); - console.log(count); - count++; - } - } - - return ports; - } - - __drawFlow(params: { [k: string]: any }) { - const position = params.position; - const gap = params.gap; - const radius = params.valveRadius; - const color = params.color; - let rotation = params.rotation; - const channelWidth = params.channelWidth; - const threedmux_flow = new paper.CompoundPath(""); - - const px = position[0]; - const py = position[1]; - const ins = params.in; - const outs = params.out; - let N; - if (ins < outs) { - N = outs; - } else { - N = ins; - rotation += 180; - } - const bottomlinelength = N * 4000; // modify, so it depends on the input N - const vertlinelength = N * 3000; // same as above - - const bottomlineleft = new paper.Point(px - channelWidth / 2, py - channelWidth / 2 + vertlinelength); - const bottomlineright = new paper.Point(px + bottomlinelength + channelWidth / 2, py + channelWidth / 2 + vertlinelength); - const channel = new paper.Path.Rectangle(bottomlineleft, bottomlineright); - - threedmux_flow.addChild(channel); - - const valvenum = Math.log(N) / Math.log(2); - const valveselect = vertlinelength / (2 * valvenum); - const branchArray = new Array(N); - const centerArray = new Array(N); - - // create base flow - for (let i = 0; i < N; i++) { - const xposbranch = i * (bottomlinelength / (N - 1)); - - const vertlinebottom = new paper.Point(px + xposbranch - channelWidth / 2, py + vertlinelength); - const vertlinetop = new paper.Point(px + xposbranch + channelWidth / 2, py); - branchArray[i] = new paper.Path.Rectangle(vertlinebottom, vertlinetop); - } - - // create output port - const portCon = new paper.Point(px + bottomlinelength / 2 - channelWidth / 2, py + vertlinelength); - const portOut = new paper.Point(px + bottomlinelength / 2 + channelWidth / 2, py + vertlinelength + N * 1000); - - const portRec = new paper.Path.Rectangle(portCon, portOut); - - threedmux_flow.addChild(portRec); - - // add valves and remove parts of channels - let cur_N = N; - const xpos = px; - let ypos = py + valveselect; - - for (let j = 0; j < valvenum; j++) { - // left side - let count1 = 0; - const increment1 = cur_N / 2; - while (count1 < N) { - for (let w = 0; w < cur_N / 2; w++) { - const current_xpos = xpos + ((count1 + w) * bottomlinelength) / (N - 1); - - const cutrec = new paper.Path.Rectangle({ - from: new paper.Point(current_xpos - channelWidth / 2, ypos - gap / 2), - to: new paper.Point(current_xpos + channelWidth / 2, ypos + gap / 2) - }); - - this.__createthreedmuxValve(threedmux_flow, current_xpos, ypos, gap, radius, rotation, channelWidth); - branchArray[count1 + w] = branchArray[count1 + w].subtract(cutrec); // remove a portion from the selected channel - } - - count1 += 2 * increment1; - } - - // right side - const ypos_adjust = vertlinelength / (2 * valvenum + 2); - let count2 = 0; - const increment2 = cur_N / 2; - ypos += ypos_adjust; - - while (count2 < N) { - for (let w = 0; w < cur_N / 2; w++) { - const current_xpos = xpos + bottomlinelength - ((count2 + w) * bottomlinelength) / (N - 1); - - const cutrec = new paper.Path.Rectangle({ - from: new paper.Point(current_xpos - channelWidth / 2, ypos - gap / 2), - to: new paper.Point(current_xpos + channelWidth / 2, ypos + gap / 2) - }); - - branchArray[N - 1 - w - count2] = branchArray[N - 1 - w - count2].subtract(cutrec); - this.__createthreedmuxValve(threedmux_flow, current_xpos, ypos, gap, radius, rotation, channelWidth); - } - count2 += increment2 + cur_N / 2; - } - ypos += ypos_adjust; - cur_N = cur_N / 2; - } - - for (let i = 0; i < N; i++) { - threedmux_flow.addChild(branchArray[i]); - // threedmux_flow.addChild(centerArray[i]); - } - - threedmux_flow.fillColor = color; - - threedmux_flow.rotate(rotation, new paper.Point(px, py)); - - return threedmux_flow; - } - - __createthreedmuxValve(compound_path: paper.CompoundPath, xpos: number, ypos: number, gap: number, radius: number, rotation: number, channel_width: number): void { - const center = new paper.Point(xpos, ypos); - - // Create the basic circle - let circ: paper.Path.Circle | paper.PathItem = new paper.Path.Circle(center, radius); - - // Add the tiny channel pieces that jut out - let rec = new paper.Path.Rectangle({ - point: new paper.Point(xpos - channel_width / 2, ypos - radius), - size: [channel_width, radius], - stokeWidth: 0 - }); - - circ = circ.unite(rec); - - rec = new paper.Path.Rectangle({ - point: new paper.Point(xpos - channel_width / 2, ypos), - size: [channel_width, radius], - stokeWidth: 0 - }); - - circ = circ.unite(rec); - - const cutout = new paper.Path.Rectangle({ - from: new paper.Point(xpos - radius, ypos - gap / 2), - to: new paper.Point(xpos + radius, ypos + gap / 2) - }); - - const valve = circ.subtract(cutout); - - compound_path.addChild(valve); - } - - __drawControl(params: { [k: string]: any }) { - const position = params.position; - const radius = params.valveRadius; - const color = params.color; - let rotation = params.rotation; - const channelWidth = params.controlChannelWidth; - const threedmux_control = new paper.CompoundPath(""); - - const px = position[0]; - const py = position[1]; - - const ins = params.in; - const outs = params.out; - - let N; - if (ins < outs) { - N = outs; - } else { - N = ins; - rotation += 180; - } - - const bottomlinelength = N * 4000; // modify, so it depends on the input N - const vertlinelength = N * 3000; // same as above - - const leftInput = px - N * 1000; - const rightInput = px + bottomlinelength + N * 1000; - let indexN = N; - const valvenum = Math.log(N) / Math.log(2); - const vertholder = vertlinelength / (2 * valvenum); - const valveselect = vertlinelength / (2 * valvenum); - - for (let i = 0; i < 2 * valvenum; i++) { - // left side - if (i % 2 === 0) { - indexN /= 2; - const cur_ind = N - indexN - 1; - const leftsideLeft = new paper.Point(leftInput, py + vertholder + (i * vertlinelength) / (2 * valvenum + 2) - channelWidth / 2); - const leftsideRight = new paper.Point(px + cur_ind * (bottomlinelength / (N - 1)), py + vertholder + (i * vertlinelength) / (2 * valvenum + 2) + channelWidth / 2); - const leftcontrol = new paper.Path.Rectangle(leftsideLeft, leftsideRight); - - threedmux_control.addChild(leftcontrol); - } - // right side - else { - const cur_ind = indexN; - const rightsideLeft = new paper.Point(px + cur_ind * (bottomlinelength / (N - 1)), py + vertholder + (i * vertlinelength) / (2 * valvenum + 2) - channelWidth / 2); - const rightsideRight = new paper.Point(rightInput, py + vertholder + (i * vertlinelength) / (2 * valvenum + 2) + channelWidth / 2); - const rightcontrol = new paper.Path.Rectangle(rightsideLeft, rightsideRight); - - threedmux_control.addChild(rightcontrol); - } - } - - let cur_N = N; - const xpos = px; - let ypos = py + valveselect; - - for (let j = 0; j < valvenum; j++) { - // left side - let count1 = 0; - const increment1 = cur_N / 2; - while (count1 < N) { - for (let w = 0; w < cur_N / 2; w++) { - const current_xpos = xpos + ((count1 + w) * bottomlinelength) / (N - 1); - const center = new paper.Point(current_xpos, ypos); - const circle = new paper.Path.Circle(center, radius); - threedmux_control.addChild(circle); - } - - count1 += 2 * increment1; - } - - // right side - const ypos_adjust = vertlinelength / (2 * valvenum + 2); - let count2 = 0; - const increment2 = cur_N / 2; - ypos += ypos_adjust; - - while (count2 < N) { - for (let w = 0; w < cur_N / 2; w++) { - const current_xpos = xpos + bottomlinelength - ((count2 + w) * bottomlinelength) / (N - 1); - const center = new paper.Point(current_xpos, ypos); - const circle = new paper.Path.Circle(center, radius); - threedmux_control.addChild(circle); - } - count2 += increment2 + cur_N / 2; - } - ypos += ypos_adjust; - cur_N = cur_N / 2; - } - - threedmux_control.fillColor = color; - threedmux_control.rotate(rotation, new paper.Point(px, py)); - - return threedmux_control; - } - - __drawInverse(params: { [k: string]: any }) { - const position = params.position; - const radius = params.valveRadius; - const color = params.color; - let rotation = params.rotation; - const threedmux_control = new paper.CompoundPath(""); - - const px = position[0]; - const py = position[1]; - - const ins = params.in; - const outs = params.out; - - let N; - if (ins < outs) { - N = outs; - } else { - N = ins; - rotation += 180; - } - - const bottomlinelength = N * 4000; // modify, so it depends on the input N - const vertlinelength = N * 3000; // same as above - - const leftInput = px - N * 1000; - const rightInput = px + bottomlinelength + N * 1000; - let indexN = N; - const valvenum = Math.log(N) / Math.log(2); - const vertholder = vertlinelength / (2 * valvenum); - const valveselect = vertlinelength / (2 * valvenum); - - let cur_N = N; - const xpos = px; - let ypos = py + valveselect; - - for (let j = 0; j < valvenum; j++) { - // left side - let count1 = 0; - const increment1 = cur_N / 2; - while (count1 < N) { - for (let w = 0; w < cur_N / 2; w++) { - const current_xpos = xpos + ((count1 + w) * bottomlinelength) / (N - 1); - const center = new paper.Point(current_xpos, ypos); - const circle = new paper.Path.Circle(center, radius); - threedmux_control.addChild(circle); - } - - count1 += 2 * increment1; - } - - // right side - const ypos_adjust = vertlinelength / (2 * valvenum + 2); - let count2 = 0; - const increment2 = cur_N / 2; - ypos += ypos_adjust; - - while (count2 < N) { - for (let w = 0; w < cur_N / 2; w++) { - const current_xpos = xpos + bottomlinelength - ((count2 + w) * bottomlinelength) / (N - 1); - const center = new paper.Point(current_xpos, ypos); - const circle = new paper.Path.Circle(center, radius); - threedmux_control.addChild(circle); - } - count2 += increment2 + cur_N / 2; - } - ypos += ypos_adjust; - cur_N = cur_N / 2; - } - - threedmux_control.fillColor = color; - threedmux_control.rotate(rotation, new paper.Point(px, py)); - - return threedmux_control; - } -} \ No newline at end of file diff --git a/src/app/library/toroidalMixer.ts b/src/app/library/toroidalMixer.ts deleted file mode 100644 index 83565379..00000000 --- a/src/app/library/toroidalMixer.ts +++ /dev/null @@ -1,254 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { Path, Point } from "paper/dist/paper-core"; -// import { LogicalLayerType, ToolPaperObject } from "../core/init"; -import { LogicalLayerType } from "../core/init"; - -export default class ToroidalMixer extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - neckAngle: "Float", - neckLength: "Float", - neckWidth: "Float", - numberOfMixers: "Float", - channelWidth: "Float", - innerDiameter: "Float", - rotation: "Float", - height: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - rotation: 0, - channelWidth: 0.8 * 1000, - neckAngle: 120, - neckLength: 1000, - neckWidth: 800, - numberOfMixers: 1, - innerDiameter: 2.46 * 1000, - height: 250 - }; - - this.__units = { - componentSpacing: "μm", - rotation: "°", - neckAngle: "°", - neckLength: "μm", - neckWidth: "μm", - numberOfMixers: "", - channelWidth: "μm", - innerDiameter: "μm", - height: "μm" - }; - - this.__minimum = { - componentSpacing: 0, - rotation: 0, - channelWidth: 10, - neckAngle: 0, - neckLength: 0, - neckWidth: 10, - numberOfMixers: 1, - innerDiameter: 10, - height: 10 - }; - - this.__maximum = { - componentSpacing: 10000, - rotation: 360, - channelWidth: 2000, - neckAngle: 360, - neckLength: 10000, - neckWidth: 2000, - numberOfMixers: 20, - innerDiameter: 12 * 1000, - height: 1200 - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - channelWidth: "channelWidth", - neckAngle: "neckAngle", - neckLength: "neckLength", - neckWidth: "neckWidth", - numberOfMixers: "numberOfMixers", - rotation: "rotation", - innerDiameter: "innerDiameter" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - channelWidth: "channelWidth", - neckAngle: "neckAngle", - neckLength: "neckLength", - neckWidth: "neckWidth", - numberOfMixers: "numberOfMixers", - rotation: "rotation", - innerDiameter: "innerDiameter" - }; - - this.__placementTool = "componentPositionTool"; - - this.__toolParams = { - position: "position" - }; - - this.__renderKeys = ["FLOW"]; - - this.__mint = "TOROIDAL MIXER"; - - this.__zOffsetKeys = { - FLOW: "height" - }; - - this.__substrateOffset = { - FLOW: "0" - }; - } - - getPorts(params: { [index: string]: any }) { - const y: number = params.position[1]; - const channelWidth: number = params.channelWidth; - const innerDiameter: number = params.innerDiameter; - const neckLength: number = params.neckLength; - const neckAngle: number = params.neckAngle; - const numberOfMixers: number = params.numberOfMixers; - const y_center: number = y + Math.abs((neckLength + channelWidth + 0.5 * innerDiameter) * Math.sin((0.5 * neckAngle * Math.PI) / 180)); - const diameter: number = 2 * (y_center - y); - const y_neckComponent: number = neckLength * Math.sin((0.5 * neckAngle * Math.PI) / 180); - - const ports: Array = []; - - ports.push(new ComponentPort(0, 0, "1", LogicalLayerType.FLOW)); - - if (numberOfMixers % 2 == 1) { - ports.push( - new ComponentPort( - 0, - (numberOfMixers - 1) * diameter - (numberOfMixers - 2) * y_neckComponent + diameter - neckLength * Math.sin((0.5 * neckAngle * Math.PI) / 180), - "2", - LogicalLayerType.FLOW - ) - ); - } else { - ports.push( - new ComponentPort( - -1 * neckLength * Math.cos((0.5 * neckAngle * Math.PI) / 180), - (numberOfMixers - 1) * diameter - (numberOfMixers - 2) * y_neckComponent + diameter - neckLength * Math.sin((0.5 * neckAngle * Math.PI) / 180), - "2", - LogicalLayerType.FLOW - ) - ); - } - - return ports; - } - - render2D(params: { [index: string]: any }, key: string): paper.CompoundPath { - const channelWidth: number = params.channelWidth; - const innerDiameter: number = params.innerDiameter; - const neckAngle: number = params.neckAngle; - const neckWidth: number = params.neckWidth; - const rotation: number = params.rotation; - const neckLength: number = params.neckLength; - const numMixers: number = params.numberOfMixers; - const x: number = params.position[0]; - const y: number = params.position[1]; - const color: any = params.color; - const serp: paper.CompoundPath = new paper.CompoundPath([]); - const x_center: number = x - (neckLength + channelWidth + 0.5 * innerDiameter) * Math.cos((0.5 * neckAngle * Math.PI) / 180); - const y_center: number = y + Math.abs((neckLength + channelWidth + 0.5 * innerDiameter) * Math.sin((0.5 * neckAngle * Math.PI) / 180)); - const center: paper.Point = new paper.Point(x_center, y_center); - const diameter: number = 2 * (y_center - y); - const y_neckComponent: number = neckLength * Math.sin((0.5 * neckAngle * Math.PI) / 180); - - let mixerUnit: paper.PathItem; - - //Initial ring - let outerCircle: paper.Path = new paper.Path.Circle(center, 0.5 * innerDiameter + channelWidth); - let innerCircle: paper.Path = new paper.Path.Circle(center, 0.5 * innerDiameter); - mixerUnit = outerCircle.subtract(innerCircle); - //Initial neck - let neck: paper.Path = new paper.Path.Rectangle(new paper.Point(x - neckLength - channelWidth, y - 0.5 * neckWidth), new paper.Size(neckLength + channelWidth, neckWidth)); - neck.rotate((-1 * neckAngle) / 2, new paper.Point(x, y)); - mixerUnit = mixerUnit.unite(neck); - //Trailing neck - neck = new paper.Path.Rectangle(new paper.Point(x - neckLength - channelWidth, y - 0.5 * neckWidth + diameter), new paper.Size(neckLength + channelWidth, neckWidth)); - neck.rotate(neckAngle / 2, new paper.Point(x, y + diameter)); - mixerUnit = mixerUnit.unite(neck); - - let y_val: number; - let x_centerAnalog: number; - let y_centerAnalog: number; - let centerAnalog: paper.Point; - let numRepeats: number = numMixers - 1; - for (let i = 1; i <= numRepeats; i++) { - y_val = y + i * diameter - (i - 1) * y_neckComponent; - if (i % 2 == 1) { - x_centerAnalog = x + (channelWidth + 0.5 * innerDiameter) * Math.cos((0.5 * neckAngle * Math.PI) / 180); - y_centerAnalog = y_val + Math.abs((channelWidth + 0.5 * innerDiameter) * Math.sin((0.5 * neckAngle * Math.PI) / 180)); - centerAnalog = new paper.Point(x_centerAnalog, y_centerAnalog); - //Add next ring - outerCircle = new paper.Path.Circle(centerAnalog, 0.5 * innerDiameter + channelWidth); - innerCircle = new paper.Path.Circle(centerAnalog, 0.5 * innerDiameter); - mixerUnit = mixerUnit.unite(outerCircle.subtract(innerCircle)); - //Complete inter-ring connection - neck = new paper.Path.Rectangle(new paper.Point(x, y_val - 0.5 * neckWidth), new paper.Size(channelWidth, neckWidth)); - neck.rotate(neckAngle / 2, new paper.Point(x, y_val)); - mixerUnit = mixerUnit.unite(neck); - //Add trailing neck - neck = new paper.Path.Rectangle( - new paper.Point(x - neckLength, y_val - 0.5 * neckWidth + (2 * channelWidth + innerDiameter) * Math.sin((0.5 * neckAngle * Math.PI) / 180)), - new paper.Size(neckLength + channelWidth, neckWidth) - ); - neck.rotate((-1 * neckAngle) / 2, new paper.Point(x, y_val + (2 * channelWidth + innerDiameter) * Math.sin((0.5 * neckAngle * Math.PI) / 180))); - mixerUnit = mixerUnit.unite(neck); - } else { - y_centerAnalog = y_val + Math.abs((channelWidth + 0.5 * innerDiameter) * Math.sin((0.5 * neckAngle * Math.PI) / 180)); - centerAnalog = new paper.Point(x_center, y_centerAnalog); - //Add next ring - outerCircle = new paper.Path.Circle(centerAnalog, 0.5 * innerDiameter + channelWidth); - innerCircle = new paper.Path.Circle(centerAnalog, 0.5 * innerDiameter); - mixerUnit = mixerUnit.unite(outerCircle.subtract(innerCircle)); - //Complete inter-ring connection - neck = new paper.Path.Rectangle( - new paper.Point(x - channelWidth - neckLength * Math.cos((0.5 * neckAngle * Math.PI) / 180), y_val - 0.5 * neckWidth), - new paper.Size(channelWidth, neckWidth) - ); - neck.rotate((-1 * neckAngle) / 2, new paper.Point(x - neckLength * Math.cos((0.5 * neckAngle * Math.PI) / 180), y_val)); - mixerUnit = mixerUnit.unite(neck); - //Add trailing neck - neck = new paper.Path.Rectangle( - new paper.Point(x - neckLength - channelWidth, y_val - 0.5 * neckWidth + diameter - neckLength * Math.sin((0.5 * neckAngle * Math.PI) / 180)), - new paper.Size(neckLength + channelWidth, neckWidth) - ); - neck.rotate(neckAngle / 2, new paper.Point(x, y_val + diameter - neckLength * Math.sin((0.5 * neckAngle * Math.PI) / 180))); - mixerUnit = mixerUnit.unite(neck); - } - } - serp.addChild(mixerUnit); - serp.fillColor = color; - serp.rotate(rotation, new paper.Point(x, y)); - return serp; - } - - render2DTarget(key: string | null, params: { [index: string]: any }): paper.CompoundPath { - if (key === null) { - key = this.__renderKeys[0]; - } - const render = this.render2D(params, key); - if (render.fillColor !== null) render.fillColor.alpha = 0.5; - return render; - } -} diff --git a/src/app/library/transition.ts b/src/app/library/transition.ts deleted file mode 100644 index e88b6f73..00000000 --- a/src/app/library/transition.ts +++ /dev/null @@ -1,116 +0,0 @@ -import Template from "./template"; -import paper from "paper"; - -export default class Transition extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - cw1: "Float", - cw2: "Float", - length: "Float", - rotation: "Float", - height: "Float" - }; - - this.__defaults = { - cw1: 0.8 * 1000, - cw2: 0.9 * 1000, - length: 1.0 * 1000, - rotation: 0, - height: 250 - }; - - this.__units = { - cw1: "μm", - cw2: "μm", - length: "μm", - rotation: "°", - height: "μm" - }; - - this.__minimum = { - cw1: 3, - cw2: 3, - length: 10, - height: 10, - rotation: 0 - }; - - this.__maximum = { - rotation: 180, - cw1: 2000, - cw2: 2000, - length: 1200, - height: 1200 - }; - - this.__featureParams = { - position: "position", - cw1: "cw1", - cw2: "cw2", - length: "length", - rotation: "rotation" - }; - - this.__targetParams = { - cw1: "cw1", - cw2: "cw2", - length: "length", - rotation: "rotation" - }; - - this.__placementTool = "PositionTool"; - - this.__toolParams = { - position: "position" - }; - - this.__renderKeys = ["FLOW"]; - - this.__mint = "TRANSITION"; - - this.__zOffsetKeys = { - FLOW: "height" - }; - - this.__substrateOffset = { - FLOW: "0" - }; - } - - render2D(params: { [k: string]: any }, key: string): paper.Path { - const position = params.position; - const cw1 = params.cw1; - const cw2 = params.cw2; - const length = params.length; - const rotation = params.rotation; - const color = params.color; - const trap = new paper.Path(); - - trap.add(new paper.Point(position[0] - cw1 / 2, position[1])); - trap.add(new paper.Point(position[0] + cw1 / 2, position[1])); - trap.add(new paper.Point(position[0] + cw2 / 2, position[1] + length)); - trap.add(new paper.Point(position[0] - cw2 / 2, position[1] + length)); - // trap.add(new paper.Point(position[0] - cw1/2, position[1])); - - trap.closed = true; - trap.fillColor = color; - return (trap.rotate(rotation, new paper.Point(position[0], position[1])) as unknown) as paper.Path; - } - - render2DTarget(key: string | null, params: { [k: string]: any }): paper.Path { - if (key === null) { - key = this.__renderKeys[0]; - } - const render = this.render2D(params, key); - render.fillColor!.alpha = 0.5; - return render; - } -} diff --git a/src/app/library/transposer.ts b/src/app/library/transposer.ts deleted file mode 100644 index e0d9fdd6..00000000 --- a/src/app/library/transposer.ts +++ /dev/null @@ -1,416 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class Transposer extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - rotation: "Float", - valveRadius: "Float", - height: "Float", - valveGap: "Float", - valveSpacing: "Float", - flowChannelWidth: "Float", - controlChannelWidth: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - rotation: 0, - valveRadius: 1.2 * 1000, - height: 250, - valveGap: 0.6 * 1000, - valveSpacing: 0.6 * 1000, - flowChannelWidth: 500, - controlChannelWidth: 500 - }; - - this.__units = { - componentSpacing: "μm", - rotation: "°", - valveRadius: "μm", - height: "μm", - valveGap: "μm", - valveSpacing: "μm", - flowChannelWidth: "μm", - controlChannelWidth: "μm" - }; - - this.__minimum = { - componentSpacing: 0, - valveRadius: 0.1 * 100, - height: 0.1 * 100, - valveGap: 0.5 * 10, - valveSpacing: 0.1 * 1000, - flowChannelWidth: 0.1, - controlChannelWidth: 0.1, - rotation: 0 - }; - - this.__maximum = { - componentSpacing: 10000, - valveRadius: 0.2 * 10000, - height: 1.2 * 1000, - valveGap: 0.1 * 10000, - valveSpacing: 0.1 * 10000, - flowChannelWidth: 0.1 * 10000, - controlChannelWidth: 0.1 * 10000, - rotation: 360 - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - rotation: "rotation", - valveRadius: "valveRadius", - valveGap: "valveGap", - valveSpacing: "valveSpacing", - flowChannelWidth: "flowChannelWidth", - controlChannelWidth: "controlChannelWidth" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - position: "position", - rotation: "rotation", - valveRadius: "valveRadius", - valveGap: "valveGap", - valveSpacing: "valveSpacing", - flowChannelWidth: "flowChannelWidth", - controlChannelWidth: "controlChannelWidth" - }; - - this.__placementTool = "multilayerPositionTool"; - - this.__toolParams = { - position: "position" - }; - - this.__renderKeys = ["FLOW", "CONTROL", "INVERSE"]; - - this.__mint = "TRANSPOSER"; - - this.__zOffsetKeys = { - FLOW: "height", - CONTROL: "height", - INVERSE: "height" - }; - - this.__substrateOffset = { - FLOW: "0", - CONTROL: "+1", - INVERSE: "0" - }; - } - - getPorts(params: { [k: string]: any }) { - const ports = []; - - const radius = params.valveRadius; - const channelWidth = params.flowChannelWidth; - const valvespacing = params.valveSpacing; - - ports.push(new ComponentPort(0, 0, "1", LogicalLayerType.FLOW)); - ports.push(new ComponentPort(6 * valvespacing + 4 * radius + 3 * channelWidth, 0, "2", LogicalLayerType.FLOW)); - ports.push(new ComponentPort(0, 2 * channelWidth + 4 * valvespacing + 2 * 2 * radius, "3", LogicalLayerType.FLOW)); - ports.push(new ComponentPort(6 * valvespacing + 4 * radius + 3 * channelWidth, 2 * channelWidth + 4 * valvespacing + 2 * 2 * radius, "4", LogicalLayerType.FLOW)); - - ports.push(new ComponentPort(-2 * radius - channelWidth / 2, channelWidth + 2 * valvespacing + 2 * radius, "5", LogicalLayerType.CONTROL)); - ports.push(new ComponentPort(5 * valvespacing + 6 * radius + 3 * channelWidth, channelWidth + 2 * valvespacing + 2 * radius, "6", LogicalLayerType.CONTROL)); - - return ports; - } - - render2D(params: { [k: string]: any }, key = "FLOW") { - if (key === "FLOW") { - return this.__drawFlow(params); - } else if (key === "CONTROL") { - return this.__drawControl(params); - } - - throw new Error("Unknown key: " + key); - - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - const ret = new paper.CompoundPath(""); - const flow = this.render2D(params, "FLOW"); - const control = this.render2D(params, "CONTROL"); - ret.addChild(control as paper.CompoundPath); - ret.addChild(flow as paper.CompoundPath); - ret.fillColor = params.color; - ret.fillColor!.alpha = 0.5; - return ret; - } - - __drawFlow(params: { [k: string]: any }) { - const position = params.position; - const valveGap = params.valveGap; - const radius = params.valveRadius; - const color = params.color; - const rotation = params.rotation; - const channelWidth = params.flowChannelWidth; - const valvespacing = params.valveSpacing; - const transposer_flow = new paper.CompoundPath(""); - - const px = position[0]; - const py = position[1]; - - // Draw top left channel - let topleftpoint = new paper.Point(px, py - channelWidth / 2); - let bottomrightpoint = new paper.Point(px + 4 * valvespacing + 2 * radius + 2 * channelWidth, py + channelWidth / 2); - let channel = new paper.Path.Rectangle(topleftpoint, bottomrightpoint); - - transposer_flow.addChild(channel); - - // Draw Valve - this.__createTransposerValve(transposer_flow, bottomrightpoint.x + radius, topleftpoint.y + channelWidth / 2, valveGap, radius, "H", channelWidth); - - // Draw top right channel - topleftpoint = new paper.Point(px + 4 * valvespacing + 4 * radius + 2 * channelWidth, py - channelWidth / 2); - bottomrightpoint = new paper.Point(px + 6 * valvespacing + 4 * radius + 3 * channelWidth, py + channelWidth / 2); - channel = new paper.Path.Rectangle(topleftpoint, bottomrightpoint); - - transposer_flow.addChild(channel); - - // Draw middle channels - topleftpoint = new paper.Point(px + 3 * valvespacing + channelWidth + 2 * radius, py + channelWidth / 2); - bottomrightpoint = new paper.Point(topleftpoint.x + channelWidth, topleftpoint.y + valvespacing); - channel = new paper.Path.Rectangle(topleftpoint, bottomrightpoint); - - transposer_flow.addChild(channel); - this.__createTransposerValve(transposer_flow, topleftpoint.x + channelWidth / 2, bottomrightpoint.y + radius, valveGap, radius, "V", channelWidth); - - // 2 - topleftpoint = new paper.Point(topleftpoint.x, bottomrightpoint.y + 2 * radius); - bottomrightpoint = new paper.Point(topleftpoint.x + channelWidth, topleftpoint.y + 2 * valvespacing + channelWidth); - channel = new paper.Path.Rectangle(topleftpoint, bottomrightpoint); - - transposer_flow.addChild(channel); - - this.__createTransposerValve(transposer_flow, topleftpoint.x + channelWidth / 2, bottomrightpoint.y + radius, valveGap, radius, "V", channelWidth); - - // 3 - topleftpoint = new paper.Point(topleftpoint.x, bottomrightpoint.y + 2 * radius); - bottomrightpoint = new paper.Point(topleftpoint.x + channelWidth, topleftpoint.y + valvespacing); - channel = new paper.Path.Rectangle(topleftpoint, bottomrightpoint); - - transposer_flow.addChild(channel); - - // Bottom Channels - topleftpoint = new paper.Point(px, py + 1.5 * channelWidth + 4 * valvespacing + 2 * 2 * radius); - bottomrightpoint = new paper.Point(topleftpoint.x + 2 * valvespacing + channelWidth, topleftpoint.y + channelWidth); - channel = new paper.Path.Rectangle(topleftpoint, bottomrightpoint); - - transposer_flow.addChild(channel); - - this.__createTransposerValve(transposer_flow, bottomrightpoint.x + radius, topleftpoint.y + channelWidth / 2, valveGap, radius, "H", channelWidth); - - // 2 - topleftpoint = new paper.Point(bottomrightpoint.x + 2 * radius, topleftpoint.y); - bottomrightpoint = new paper.Point(topleftpoint.x + 4 * valvespacing + 2 * channelWidth + 2 * radius, topleftpoint.y + channelWidth); - channel = new paper.Path.Rectangle(topleftpoint, bottomrightpoint); - - transposer_flow.addChild(channel); - - // Draw the right channels - topleftpoint = new paper.Point(px + 5 * valvespacing + 2 * channelWidth + 4 * radius, py + channelWidth / 2); - bottomrightpoint = new paper.Point(topleftpoint.x + channelWidth, topleftpoint.y + valvespacing); - channel = new paper.Path.Rectangle(topleftpoint, bottomrightpoint); - - transposer_flow.addChild(channel); - - this.__createTransposerValve(transposer_flow, topleftpoint.x + channelWidth / 2, bottomrightpoint.y + radius, valveGap, radius, "V", channelWidth); - - // 2 - topleftpoint = new paper.Point(topleftpoint.x, bottomrightpoint.y + 2 * radius); - bottomrightpoint = new paper.Point(topleftpoint.x + channelWidth, topleftpoint.y + valvespacing + channelWidth); - channel = new paper.Path.Rectangle(topleftpoint, bottomrightpoint); - - transposer_flow.addChild(channel); - - transposer_flow.fillColor = color; - - // Draw the left channels - topleftpoint = new paper.Point(px + valvespacing, py + 1.5 * channelWidth + 2 * valvespacing + 2 * radius); - bottomrightpoint = new paper.Point(topleftpoint.x + channelWidth, topleftpoint.y + valvespacing); - channel = new paper.Path.Rectangle(topleftpoint, bottomrightpoint); - - transposer_flow.addChild(channel); - - this.__createTransposerValve(transposer_flow, topleftpoint.x + channelWidth / 2, bottomrightpoint.y + radius, valveGap, radius, "V", channelWidth); - - // 2 - topleftpoint = new paper.Point(topleftpoint.x, bottomrightpoint.y + 2 * radius); - bottomrightpoint = new paper.Point(topleftpoint.x + channelWidth, topleftpoint.y + valvespacing + channelWidth); - channel = new paper.Path.Rectangle(topleftpoint, bottomrightpoint); - - transposer_flow.addChild(channel); - - transposer_flow.fillColor = color; - - transposer_flow.rotate(rotation, new paper.Point(px + 3 * valvespacing + 1.5 * channelWidth + 2 * radius, py + channelWidth + 2 * valvespacing + 2 * radius)); - - return transposer_flow; - } - - __createTransposerValve(compound_path: paper.CompoundPath, xpos: number, ypos: number, valveGap: number, radius: number, orientation: string, channel_width: number): void { - const center = new paper.Point(xpos, ypos); - - // Create the basic circle - let circ: paper.Path.Circle | paper.PathItem = new paper.Path.Circle(center, radius); - - // Add the tiny channel pieces that jut out - let rec = new paper.Path.Rectangle({ - point: new paper.Point(xpos - channel_width / 2, ypos - radius), - size: [channel_width, radius], - stokeWidth: 0 - }); - - circ = circ.unite(rec); - - rec = new paper.Path.Rectangle({ - point: new paper.Point(xpos - channel_width / 2, ypos), - size: [channel_width, radius], - stokeWidth: 0 - }); - - circ = circ.unite(rec); - - const cutout = new paper.Path.Rectangle({ - from: new paper.Point(xpos - radius, ypos - valveGap / 2), - to: new paper.Point(xpos + radius, ypos + valveGap / 2) - }); - - // cutout.fillColor = "white"; - const valve = circ.subtract(cutout); - - // TODO Rotate - if (orientation === "H") { - valve.rotate(90, center); - } - - compound_path.addChild(valve); - } - - __drawControl(params: { [k: string]: any }) { - const position = params.position; - const valveGap = params.valveGap; - const radius = params.valveRadius; - const color = params.color; - const rotation = params.rotation; - const channelWidth = params.controlChannelWidth; - const valvespacing = params.valveSpacing; - const transposer_control = new paper.CompoundPath(""); - - const px = position[0]; - const py = position[1]; - - // Top right valve - let center = new paper.Point(px + 4 * valvespacing + 2 * channelWidth + 2 * radius + radius, py); - let circle = new paper.Path.Circle(center, radius); - transposer_control.addChild(circle); - - let topLeft = new paper.Point(px + 4 * valvespacing + 2 * channelWidth + 2 * radius + radius - channelWidth / 2, py - 2 * radius); - let bottomRight = new paper.Point(px + 4 * valvespacing + 2 * channelWidth + 2 * radius + radius + channelWidth / 2, py); - transposer_control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(px - 2 * radius, py - 2 * radius - channelWidth / 2); - bottomRight = new paper.Point(px + 4 * valvespacing + 2 * channelWidth + 2 * radius + radius + channelWidth / 2, py - 2 * radius + channelWidth / 2); - transposer_control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // 2nd row valves - - center = new paper.Point(px + 1.5 * channelWidth + 3 * valvespacing + 2 * radius, py + channelWidth / 2 + valvespacing + radius); - circle = new paper.Path.Circle(center, radius); - transposer_control.addChild(circle); - - let crosschannelstart = center; - - center = new paper.Point(center.x + 2 * valvespacing + 2 * radius + channelWidth, py + channelWidth / 2 + valvespacing + radius); - circle = new paper.Path.Circle(center, radius); - transposer_control.addChild(circle); - - let crosschannelend = center; - - // Draw the cross channel connecting the 2nd row valves - let rect = new paper.Path.Rectangle({ - from: new paper.Point(crosschannelstart.x, crosschannelstart.y - channelWidth / 2), - to: new paper.Point(crosschannelend.x, crosschannelstart.y + channelWidth / 2) - }); - - transposer_control.addChild(rect); - - topLeft = new paper.Point(crosschannelend.x, crosschannelstart.y - channelWidth / 2); - bottomRight = new paper.Point(crosschannelend.x + 2 * radius, crosschannelstart.y + channelWidth / 2); - transposer_control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(crosschannelend.x + 2 * radius - channelWidth / 2, crosschannelstart.y - channelWidth / 2); - bottomRight = new paper.Point(crosschannelend.x + 2 * radius + channelWidth / 2, py + 1.5 * channelWidth + 3 * valvespacing + 2 * radius + radius); - transposer_control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // 3rd Row valves - - center = new paper.Point(px + 0.5 * channelWidth + valvespacing, py + 1.5 * channelWidth + 3 * valvespacing + 2 * radius + radius); - circle = new paper.Path.Circle(center, radius); - transposer_control.addChild(circle); - - crosschannelstart = center; - - center = new paper.Point(center.x + 2 * valvespacing + 2 * radius + channelWidth, center.y); - circle = new paper.Path.Circle(center, radius); - transposer_control.addChild(circle); - - crosschannelend = center; - - // Draw the cross channel connecting the 3nd row valves - rect = new paper.Path.Rectangle({ - from: new paper.Point(crosschannelstart.x, crosschannelstart.y - channelWidth / 2), - to: new paper.Point(crosschannelend.x, crosschannelstart.y + channelWidth / 2) - }); - - transposer_control.addChild(rect); - - topLeft = new paper.Point(crosschannelend.x, crosschannelstart.y - channelWidth / 2); - bottomRight = new paper.Point(center.x + 2 * valvespacing + 4 * radius + channelWidth + channelWidth / 2, crosschannelstart.y + channelWidth / 2); - transposer_control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // Bottom Row valve - center = new paper.Point(px + channelWidth + 2 * valvespacing + radius, py + 4 * valvespacing + 4 * radius + 2 * channelWidth); - circle = new paper.Path.Circle(center, radius); - transposer_control.addChild(circle); - - topLeft = new paper.Point(px - 2 * radius - channelWidth / 2, py - 2 * radius - channelWidth / 2); - bottomRight = new paper.Point(px - 2 * radius + channelWidth / 2, py + 4 * valvespacing + 6 * radius + 2 * channelWidth); - transposer_control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(px - 2 * radius - channelWidth / 2, py + 4 * valvespacing + 6 * radius + 2 * channelWidth - channelWidth / 2); - bottomRight = new paper.Point(px + channelWidth + 2 * valvespacing + radius, py + 4 * valvespacing + 6 * radius + 2 * channelWidth + channelWidth / 2); - transposer_control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - topLeft = new paper.Point(px + channelWidth + 2 * valvespacing + radius - channelWidth / 2, py + 4 * valvespacing + 4 * radius + 2 * channelWidth); - bottomRight = new paper.Point(px + channelWidth + 2 * valvespacing + radius + channelWidth / 2, py + 4 * valvespacing + 6 * radius + 2 * channelWidth + channelWidth / 2); - transposer_control.addChild(new paper.Path.Rectangle(topLeft, bottomRight)); - - // Finally we draw the cross channel - const topleftpoint = new paper.Point(px + valvespacing, py + channelWidth / 2 + 2 * radius + 2 * valvespacing); - const bottomleftpoint = new paper.Point(topleftpoint.x + +4 * valvespacing + 3 * channelWidth + 4 * radius, topleftpoint.y + channelWidth); - const rectangle = new paper.Path.Rectangle(topleftpoint, bottomleftpoint); - transposer_control.addChild(rectangle); - - transposer_control.rotate(rotation, new paper.Point(px + 3 * valvespacing + 1.5 * channelWidth + 2 * radius, py + channelWidth + 2 * valvespacing + 2 * radius)); - - transposer_control.fillColor = color; - return transposer_control; - } -} diff --git a/src/app/library/tree.ts b/src/app/library/tree.ts deleted file mode 100644 index cecb6597..00000000 --- a/src/app/library/tree.ts +++ /dev/null @@ -1,283 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class Tree extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - flowChannelWidth: "Float", - rotation: "Float", - spacing: "Float", - in: "Integer", - out: "Integer", - width: "Float", - height: "Float", - stageLength: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - flowChannelWidth: 0.8 * 1000, - rotation: 0, - spacing: 4 * 1000, - in: 1, - out: 8, - width: 2.46 * 1000, - height: 250, - stageLength: 4000 - }; - - this.__units = { - componentSpacing: "μm", - flowChannelWidth: "μm", - rotation: "°", - spacing: "μm", - in: "", - out: "", - width: "μm", - height: "μm", - stageLength: "μm" - }; - - this.__minimum = { - componentSpacing: 0, - flowChannelWidth: 10, - spacing: 30, - in: 1, - out: 2, - width: 60, - height: 10, - stageLength: 100, - rotation: 0 - }; - - this.__maximum = { - componentSpacing: 10000, - flowChannelWidth: 2000, - spacing: 12000, - in: 1, - out: 128, - width: 12 * 1000, - height: 1200, - stageLength: 6000, - rotation: 360 - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - flowChannelWidth: "flowChannelWidth", - rotation: "rotation", - spacing: "spacing", - width: "width", - in: "in", - out: "out", - stageLength: "stageLength" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - flowChannelWidth: "flowChannelWidth", - rotation: "rotation", - spacing: "spacing", - width: "width", - in: "in", - out: "out", - stageLength: "stageLength" - }; - - this.__placementTool = "componentPositionTool"; - - this.__toolParams = { - position: "position" - }; - - this.__renderKeys = ["FLOW"]; - - this.__mint = "TREE"; - - this.__zOffsetKeys = { - FLOW: "height" - }; - - this.__substrateOffset = { - FLOW: "0" - }; - } - - getPorts(params: { [k: string]: any }) { - const ports = []; - const cw = params.flowChannelWidth; - const spacing = params.spacing; - const ins = params.in; - const outs = params.out; - let leafs; - if (ins < outs) { - leafs = outs; - } else { - leafs = ins; - } - const stagelength = params.stageLength; - - const levels = Math.ceil(Math.log2(leafs)); - const w = spacing * (leafs / 2 + 1); - - const length = levels * (cw + stagelength) + stagelength; - const width = 2 * 0.5 * w * 2 * Math.pow(0.5, levels); - - ports.push(new ComponentPort(0, 0, "1", LogicalLayerType.FLOW)); - - for (let i = 0; i < leafs; i++) { - ports.push(new ComponentPort(((leafs - 1) * width) / 2 - i * width, length, (2 + i).toString(), LogicalLayerType.FLOW)); - } - - return ports; - } - - render2D(params: { [k: string]: any }, key: string): paper.CompoundPath { - const position = params.position; - const cw = params.flowChannelWidth; - const rotation = params.rotation; - const spacing = params.spacing; - const ins = params.in; - const outs = params.out; - let leafs; - if (ins < outs) { - leafs = outs; - } else { - leafs = ins; - } - const color = params.color; - const stagelength = params.stageLength; - const px = position[0]; - const py = position[1]; - - const levels = Math.ceil(Math.log2(leafs)); - let isodd = false; // This is used to figure out how many lines have to be made - if (leafs % 2 === 0) { - isodd = false; - } else { - isodd = true; - } - const w = spacing * (leafs / 2 + 1); - const l = (levels + 1) * stagelength; - - // console.log("CW: " + cw + " levels: "+ levels + " width: " + w + " length: " + l) - - const treepath = new paper.CompoundPath(""); - - this.__generateTwig(treepath, px, py, cw, stagelength, w, 1, levels); - - // Draw the tree - - treepath.fillColor = color; - return (treepath.rotate(rotation, new paper.Point(px, py)) as unknown) as paper.CompoundPath; - } - - __generateTwig(treepath: paper.CompoundPath, px: number, py: number, cw: number, stagelength: number, newspacing: number, level: number, maxlevel: number, islast = false): void { - // var newspacing = 2 * (spacing + cw); - const hspacing = newspacing / 2; - const lex = px - 0.5 * newspacing; - const ley = py + cw + stagelength; - const rex = px + 0.5 * newspacing; - const rey = py + cw + stagelength; - - if (level === maxlevel) { - islast = true; - // console.log("Final Spacing: " + newspacing) - } - - this.__drawtwig(treepath, px, py, cw, stagelength, newspacing, islast); - // drawtwig(treepath, lex, ley, cw, stagelength, hspacing, islast); - // drawtwig(treepath, rex, rey, cw, stagelength, hspacing, islast); - - if (!islast) { - this.__generateTwig(treepath, lex, ley, cw, stagelength, hspacing, level + 1, maxlevel); - this.__generateTwig(treepath, rex, rey, cw, stagelength, hspacing, level + 1, maxlevel); - } - } - - __drawtwig(treepath: paper.CompoundPath, px: number, py: number, cw: number, stagelength: number, spacing: number, drawleafs = false): paper.CompoundPath { - // stem - let startPoint = new paper.Point(px - cw / 2, py); - let endPoint = new paper.Point(px + cw / 2, py + stagelength); - let rec = new paper.Path.Rectangle({ - from: startPoint, - to: endPoint, - radius: 0, - strokeWidth: 0 - }); - - treepath.addChild(rec); - - // Draw 2 leafs - // left leaf - const lstartx = px - 0.5 * (cw + spacing); - const lendx = lstartx + cw; - const lstarty = py + stagelength + cw; - const lendy = lstarty + stagelength; - - // //right leaf - const rstartx = px + 0.5 * (spacing - cw); - const rendx = rstartx + cw; - const rstarty = py + stagelength + cw; - const rendy = rstarty + stagelength; - - if (drawleafs) { - startPoint = new paper.Point(lstartx, lstarty); - endPoint = new paper.Point(lendx, lendy); - rec = new paper.Path.Rectangle({ - from: startPoint, - to: endPoint, - radius: 0, - strokeWidth: 0 - }); - treepath.addChild(rec); - - startPoint = new paper.Point(rstartx, rstarty); - endPoint = new paper.Point(rendx, rendy); - rec = new paper.Path.Rectangle({ - from: startPoint, - to: endPoint, - radius: 0, - strokeWidth: 0 - }); - treepath.addChild(rec); - } - - // Horizontal bar - const hstartx = px - 0.5 * (cw + spacing); - const hendx = rendx; - const hstarty = py + stagelength; - const hendy = hstarty + cw; - startPoint = new paper.Point(hstartx, hstarty); - endPoint = new paper.Point(hendx, hendy); - rec = new paper.Path.Rectangle({ - from: startPoint, - to: endPoint, - radius: 0, - strokeWidth: 0 - }); - treepath.addChild(rec); - return treepath; - } - - render2DTarget(key: string | null, params: { [k: string]: any }): paper.CompoundPath { - if (key === null) { - key = this.__renderKeys[0]; - } - const render = this.render2D(params, key); - render.fillColor!.alpha = 0.5; - return render; - } -} diff --git a/src/app/library/valve.ts b/src/app/library/valve.ts deleted file mode 100644 index a6282780..00000000 --- a/src/app/library/valve.ts +++ /dev/null @@ -1,135 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType, ValveType } from "../core/init"; -import ValveTemplate from "./valveTemplate"; - -export default class Valve extends ValveTemplate { - constructor(valveType: ValveType) { - super(valveType); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - rotation: "Float", - length: "Float", - width: "Float", - height: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - rotation: 0, - width: 1.23 * 1000, - length: 4.92 * 1000, - height: 250 - }; - - this.__units = { - componentSpacing: "μm", - rotation: "°", - length: "μm", - width: "μm", - height: "μm" - }; - - this.__minimum = { - componentSpacing: 0, - rotation: 0, - width: 30, - length: 120, - height: 10 - }; - - this.__maximum = { - componentSpacing: 10000, - rotation: 180, - width: 6000, - length: 24 * 1000, - height: 1200 - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - length: "length", - width: "width", - rotation: "rotation" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - length: "length", - width: "width", - rotation: "rotation" - }; - - this.__placementTool = "valveInsertionTool"; - - this.__toolParams = { - position: "position" - }; - - this.__renderKeys = ["CONTROL"]; - - this.__mint = "VALVE"; - - this.__zOffsetKeys = { - CONTROL: "height" - }; - - this.__substrateOffset = { - CONTROL: "+1" - }; - } - - getPorts(params: { [k: string]: any }) { - const l = params.length; - const w = params.width; - - const ports = []; - - ports.push(new ComponentPort(0, 0, "1", LogicalLayerType.CONTROL)); - - return ports; - } - - render2D(params: { [k: string]: any }, key = "CONTROL") { - const position = params.position; - const px = position[0]; - const py = position[1]; - const l = params.length; - const w = params.width; - const color = params.color; - const rotation = params.rotation; - const startX = px - w / 2; - const startY = py - l / 2; - const endX = px + w / 2; - const endY = py + l / 2; - const startPoint = new paper.Point(startX, startY); - const endPoint = new paper.Point(endX, endY); - const rec = new paper.Path.Rectangle({ - from: startPoint, - to: endPoint, - radius: 0, - fillColor: color, - strokeWidth: 0 - }); - rec.rotate(rotation, new paper.Point(px, py)); - let compoundPath = new paper.CompoundPath(rec); - compoundPath.fillColor = color; - return (compoundPath); - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - const render = this.render2D(params, "CONTROL"); - render.fillColor = params.color; - render.fillColor!.alpha = 0.5; - return render; - } -} diff --git a/src/app/library/valve3D.ts b/src/app/library/valve3D.ts deleted file mode 100644 index 654798d9..00000000 --- a/src/app/library/valve3D.ts +++ /dev/null @@ -1,191 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType, ValveType } from "../core/init"; -import ValveTemplate from "./valveTemplate"; - -export default class Valve3D extends ValveTemplate { - constructor(valveType: ValveType) { - super(valveType); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - rotation: "Float", - valveRadius: "Float", - height: "Float", - gap: "Float", - width: "Float", - length: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - rotation: 0, - valveRadius: 1.2 * 1000, - height: 250, - gap: 0.6 * 1000, - width: 2.4 * 1000, - length: 2.4 * 1000 - }; - - this.__units = { - componentSpacing: "μm", - valveRadius: "μm", - height: "μm", - gap: "μm", - width: "μm", - length: "μm", - rotation: "°" - }; - - this.__minimum = { - componentSpacing: 0, - valveRadius: 0.1 * 100, - height: 0.1 * 100, - gap: 0.5 * 10, - rotation: 0, - width: 10, - length: 10 - - }; - - this.__maximum = { - componentSpacing: 10000, - valveRadius: 0.3 * 10000, - height: 1.2 * 1000, - gap: 0.1 * 10000, - rotation: 180, - width: 3 * 1000, - length: 3 * 1000 - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - rotation: "rotation", - radius1: "valveRadius", - radius2: "valveRadius", - valveRadius: "valveRadius", - gap: "gap" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - position: "position", - rotation: "rotation", - radius1: "valveRadius", - radius2: "valveRadius", - valveRadius: "valveRadius", - gap: "gap" - }; - - this.__placementTool = "valveInsertionTool"; - - this.__toolParams = { - position: "position" - }; - - this.__renderKeys = ["FLOW", "CONTROL", "INVERSE"]; - - this.__mint = "VALVE3D"; - - this.__zOffsetKeys = { - FLOW: "height", - CONTROL: "height", - INVERSE: "height" - }; - - this.__substrateOffset = { - FLOW: "0", - CONTROL: "+1", - INVERSE: "0" - }; - - this.__childFeatureMacros = [ - "VALVE3D GAP", - "VALVE3D FLOW", - ]; - } - - getPorts(params: { [k: string]: any }) { - const ports = []; - - ports.push(new ComponentPort(0, 0, "1", LogicalLayerType.CONTROL)); - - return ports; - } - - __drawFlow(params: { [k: string]: any }) { - const position = params.position; - const gap = params.gap; - const radius = params.valveRadius; - const color = params.color; - const rotation = params.rotation; - - const center = new paper.Point(position[0], position[1]); - // let h0p0, h0p1, h0p2, h1p0, h1p1, h1p2; - const circ = new paper.Path.Circle(center, radius); - // circ.fillColor = color; - // if (String(color) === "3F51B5") { - const cutout = new paper.Path.Rectangle({ - from: new paper.Point(position[0] - radius, position[1] - gap / 2), - to: new paper.Point(position[0] + radius, position[1] + gap / 2) - }); - // cutout.fillColor = "white"; - const valve = circ.subtract(cutout); - valve.rotate(rotation, center); - valve.fillColor = color; - return valve; - } - - __drawControl(params: { [k: string]: any }) { - const position = params.position; - const gap = params.gap; - const radius = params.valveRadius; - const color = params.color; - const rotation = params.rotation; - const center = new paper.Point(position[0], position[1]); - // let h0p0, h0p1, h0p2, h1p0, h1p1, h1p2; - const circ = new paper.Path.Circle(center, radius); - circ.fillColor = color; - return circ; - } - - render2D(params: { [k: string]: any }, key = "FLOW") { - if (key === "FLOW") { - return this.__drawFlow(params); - } else if (key === "CONTROL") { - return this.__drawControl(params); - } else if (key === "INVERSE") { - return this.__drawInverseFlow(params); - } else { - throw new Error("No render procedure defined for component:" + this.__mint + ", key: " + key); - } - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - const render = this.render2D(params, "FLOW"); - render.fillColor!.alpha = 0.5; - return render; - } - - __drawInverseFlow(params: { [k: string]: any }): paper.PathItem { - const position = params.position; - const gap = params.gap; - const radius = params.valveRadius; - const color = params.color; - console.log("Color:", color); - const rotation = params.rotation; - const center = new paper.Point(position[0], position[1]); - // let h0p0, h0p1, h0p2, h1p0, h1p1, h1p2; - const circ = new paper.Path.Circle(center, radius); - circ.fillColor = color; - return (circ.rotate(rotation, center) as unknown) as paper.Path.Circle; - } -} diff --git a/src/app/library/valveTemplate.ts b/src/app/library/valveTemplate.ts deleted file mode 100644 index fdf0dcdf..00000000 --- a/src/app/library/valveTemplate.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { extend } from "vue/types/umd"; -import Template from "./template"; -import { ValveType } from "../core/init"; - -export default class ValveTemplate extends Template{ - protected _valveType: ValveType = ValveType.NORMALLY_OPEN; - constructor(valveType: ValveType) { - super(); - this._valveType = valveType; - } - - get valveType(): ValveType { - return this._valveType; - } - -} \ No newline at end of file diff --git a/src/app/library/via.ts b/src/app/library/via.ts deleted file mode 100644 index abe3ac30..00000000 --- a/src/app/library/via.ts +++ /dev/null @@ -1,105 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; - -export default class Via extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - radius: "Float", - height: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - radius: 0.7 * 1000, - height: 0 - }; - - this.__units = { - componentSpacing: "μm", - radius: "μm", - height: "μm" - }; - - this.__minimum = { - componentSpacing: 0, - radius: 0.8 * 10, - height: 0 - }; - - this.__maximum = { - componentSpacing: 10000, - radius: 2000, - height: 0 - }; - - this.__placementTool = "componentPositionTool"; - - this.__toolParams = { - position: "position" - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - radius: "radius" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - radius: "radius" - }; - - this.__renderKeys = ["FLOW"]; - - this.__mint = "VIA"; - - this.__zOffsetKeys = { - FLOW: "height" - }; - - this.__substrateOffset = { - FLOW: "0" - }; - } - - getPorts(params: { [k: string]: any }) { - const radius = params.radius; - - const ports = []; - - ports.push(new ComponentPort(0, 0, "1", LogicalLayerType.FLOW)); - - return ports; - } - - render2D(params: { [k: string]: any }, key: string) { - // Regardless of the key... - const position = params.position; - const radius = params.radius; - const color1 = params.color; - const pos = new paper.Point(position[0], position[1]); - const outerCircle = new paper.Path.Circle(pos, radius); - outerCircle.fillColor = color1; - return outerCircle; - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - if (key === null) { - key = this.__renderKeys[0]; - } - const render = this.render2D(params, key); - render.fillColor!.alpha = 0.5; - return render; - } -} diff --git a/src/app/library/ytree.ts b/src/app/library/ytree.ts deleted file mode 100644 index edc487eb..00000000 --- a/src/app/library/ytree.ts +++ /dev/null @@ -1,250 +0,0 @@ -import Template from "./template"; -import paper from "paper"; -import ComponentPort from "../core/componentPort"; -import { LogicalLayerType } from "../core/init"; -import { CompoundPath } from "paper/dist/paper-core"; - -export default class YTree extends Template { - constructor() { - super(); - } - - __setupDefinitions(): void { - this.__unique = { - position: "Point" - }; - - this.__heritable = { - componentSpacing: "Float", - flowChannelWidth: "Float", - rotation: "Float", - spacing: "Float", - in: "Integer", - out: "Integer", - width: "Float", - height: "Float", - stageLength: "Float" - }; - - this.__defaults = { - componentSpacing: 1000, - flowChannelWidth: 0.8 * 1000, - rotation: 0, - spacing: 4 * 1000, - in: 1, - out: 8, - width: 2.46 * 1000, - height: 250, - stageLength: 4000 - }; - - this.__units = { - componentSpacing: "μm", - flowChannelWidth: "μm", - rotation: "°", - spacing: "μm", - in: "", - out: "", - width: "μm", - height: "μm", - stageLength: "μm" - }; - - this.__minimum = { - componentSpacing: 0, - flowChannelWidth: 10, - spacing: 30, - in: 1, - out: 2, - width: 60, - height: 10, - stageLength: 100, - rotation: 0 - }; - - this.__maximum = { - componentSpacing: 10000, - flowChannelWidth: 2000, - spacing: 12000, - in: 1, - out: 128, - width: 12 * 1000, - height: 1200, - stageLength: 6000, - rotation: 360 - }; - - this.__featureParams = { - componentSpacing: "componentSpacing", - position: "position", - flowChannelWidth: "flowChannelWidth", - rotation: "rotation", - spacing: "spacing", - width: "width", - in: "in", - out: "out", - stageLength: "stageLength" - }; - - this.__targetParams = { - componentSpacing: "componentSpacing", - flowChannelWidth: "flowChannelWidth", - rotation: "rotation", - spacing: "spacing", - in: "in", - out: "out", - stageLength: "stageLength" - }; - - this.__placementTool = "componentPositionTool"; - - this.__toolParams = { - position: "position" - }; - - this.__renderKeys = ["FLOW"]; - - this.__mint = "YTREE"; - - this.__zOffsetKeys = { - FLOW: "height" - }; - - this.__substrateOffset = { - FLOW: "0" - }; - } - - getPorts(params: { [k: string]: any }) { - const ports = []; - const cw = params.flowChannelWidth; - const spacing = params.spacing; - const ins = params.in; - const outs = params.out; - let rotation = params.rotation; - let leafs; - if (ins < outs) { - leafs = outs; - } else { - leafs = ins; - rotation += 180; - } - const stagelength = params.stageLength; - - const levels = Math.ceil(Math.log2(leafs)); - const w = spacing * (leafs / 2 + 1); - - const length = levels * stagelength; - const width = 2 * 0.5 * w * 2 * Math.pow(0.5, levels); - - ports.push(new ComponentPort(0, -cw / 2, "1", LogicalLayerType.FLOW)); - - for (let i = 0; i < leafs; i++) { - ports.push(new ComponentPort(((leafs - 1) * width) / 2 - i * width, length + cw / 2, (2 + i).toString(), LogicalLayerType.FLOW)); - } - - return ports; - } - - render2D(params: { [k: string]: any }, key: string) { - const position = params.position; - const cw = params.flowChannelWidth; - let rotation = params.rotation; - const spacing = params.spacing; - const ins = params.in; - const outs = params.out; - let leafs; - if (ins < outs) { - leafs = outs; - } else { - leafs = ins; - rotation += 180; - } - const color = params.color; - const stagelength = params.stageLength; - const px = position[0]; - const py = position[1]; - - const levels = Math.ceil(Math.log2(leafs)); - let isodd = false; // This is used to figure out how many lines have to be made - if (leafs % 2 === 0) { - isodd = false; - } else { - isodd = true; - } - const w = spacing * (leafs / 2 + 1); - const l = (levels + 1) * stagelength; - - const treepath = new paper.CompoundPath(""); - - this.__generateYTwig(treepath, px, py, cw, stagelength, w, 1, levels); - - // Draw the tree - - treepath.fillColor = color; - treepath.rotate(rotation, new paper.Point(px, py)); - - return treepath; - } - - render2DTarget(key: string | null, params: { [k: string]: any }) { - if (key === null) { - key = this.__renderKeys[0]; - } - const render = this.render2D(params, key); - render.fillColor!.alpha = 0.5; - return render; - } - - __generateYTwig(treepath: paper.CompoundPath, px: number, py: number, cw: number, stagelength: number, newspacing: number, level: number, maxlevel: number, islast = false): void { - const hspacing = newspacing / 2; - const lex = px - 0.5 * newspacing; - const ley = py + stagelength; - const rex = px + 0.5 * newspacing; - const rey = py + stagelength; - - if (level === maxlevel) { - islast = true; - } - - this.__drawYtwig(treepath, px, py, cw, stagelength, newspacing, islast); - - if (!islast) { - this.__generateYTwig(treepath, lex, ley, cw, stagelength, hspacing, level + 1, maxlevel); - this.__generateYTwig(treepath, rex, rey, cw, stagelength, hspacing, level + 1, maxlevel); - } - } - - __drawYtwig(treepath: paper.CompoundPath, px: number, py: number, cw: number, stagelength: number, spacing: number, drawleafs = false): paper.CompoundPath { - const pivotpoint = new paper.Point(px, py); - - // stem - const startPoint = new paper.Point(px - cw / 2, py - cw / 2); - - const angle = Math.atan(spacing / 2 / stagelength); - - const h = spacing / 2 / Math.sin(angle) + cw; - - // left leaf - let rec = new paper.Path.Rectangle({ - size: [cw, h], - point: startPoint, - radius: cw / 2, - stokeWidth: 0 - }); - rec.rotate((angle * 180) / Math.PI, pivotpoint); - treepath.addChild(rec); - - // right leaf - rec = new paper.Path.Rectangle({ - size: [cw, h], - point: startPoint, - radius: cw / 2, - stokeWidth: 0 - }); - rec.rotate((-angle * 180) / Math.PI, pivotpoint); - treepath.addChild(rec); - - return treepath; - } -} diff --git a/src/app/manufacturing/cncGenerator.ts b/src/app/manufacturing/cncGenerator.ts deleted file mode 100644 index 62f2fec5..00000000 --- a/src/app/manufacturing/cncGenerator.ts +++ /dev/null @@ -1,168 +0,0 @@ -import ManufacturingLayer from "./manufacturingLayer"; -import DepthFeatureMap from "./depthFeatureMap"; -import { LogicalLayerType } from "../core/init"; - -import Device from "../core/device"; -import Layer from "../core/layer"; -import Feature from "../core/feature"; -import viewManager from "../view/viewManager"; -import paper from "paper"; -import { DFMType } from "./manufacturingInfo"; - -/** - * GNCGenerator class - */ -export default class CNCGenerator { - __device: Device; - __viewManagerDelegate: viewManager; - __svgData: Map; - - /** - * Default Constructor of GNCGenerator object. - * @param {Device} device Device object - * @param {*} viewManagerDelegate - */ - constructor(device: Device, viewManagerDelegate: viewManager) { - this.__device = device; - this.__viewManagerDelegate = viewManagerDelegate; - - this.__svgData = new Map(); - } - - /** - * Gets the SVG output - * @returns {} - * @memberof CNCGenerator - */ - getSVGOutputs(): Map { - return this.__svgData; - } - - /** - * Generate the port layers - * @memberof CNCGenerator - * @returns {void} - */ - generatePortLayers(): void { - - console.log("Port layers called and not executed, functionality moved to generateDepthLayers"); - } - - /** - * Generates separate mfglayers and svgs for each of the depth layers - * @returns {void} - * @memberof CNCGenerator - */ - generateDepthLayers(): void { - // Generate a manufacturing layer for each logical layer, - // substrate, dpeth combination in device - // and output to svg - - const layers: Array = this.__device.layers; - - const mfglayers: Array = []; - let isControl: boolean = false; - - const manufacturingLayerMap: Map = new Map(); - for (const i in layers) { - const layer: Layer = layers[i]; - - const features: { [index: string]: Feature } = layer.features; - - if (layer.type === LogicalLayerType.CONTROL) { - isControl = true; - } - - for (const key in features) { - const feature: Feature = features[key]; - - let manufacturingLayerName: string; - if (feature.manufacturingInfo.substrate !== null) { - manufacturingLayerName = - feature.manufacturingInfo.modifier + - "_" + - feature.manufacturingInfo.layertype + - "_" + - feature.manufacturingInfo.substrate.toString() + - "_" + - feature.manufacturingInfo.depth; - } else { - throw new Error("Manufacturing layer name failed to be generated"); - } - - if (manufacturingLayerMap.has(manufacturingLayerName)) { - const manufacturingLayer: ManufacturingLayer | undefined = manufacturingLayerMap.get(manufacturingLayerName); - let issuccessful: boolean; - if (manufacturingLayer != undefined) { - issuccessful = manufacturingLayer.addFeature(this.__viewManagerDelegate.view.getRenderedFeature(feature.ID)); - if (!issuccessful) console.error("Could not find the feature for the corresponding id: " + feature.ID); - manufacturingLayerMap.set(manufacturingLayerName, manufacturingLayer); - } else { - throw new Error("manufacturingLayer undefined"); - } - } else { - const odd: number = feature.manufacturingInfo.substrate % 2; - let flip: boolean = false; - if (odd == 1) flip = true; - const manufacturingLayer = new ManufacturingLayer(manufacturingLayerName, flip); - const issuccessful: boolean = manufacturingLayer.addFeature(this.__viewManagerDelegate.view.getRenderedFeature(feature.ID)); - if (!issuccessful) console.error("Could not find the feature for the corresponding id: " + feature.ID); - manufacturingLayerMap.set(manufacturingLayerName, manufacturingLayer); - } - } - } - - manufacturingLayerMap.forEach((manufacturingLayer, manufacturingLayerName) => { - if (manufacturingLayer.flip) { - manufacturingLayer.flipX(); - } - mfglayers.push(manufacturingLayer); - }); - - console.log("XY Manufacturing Layers:", mfglayers); - const ref = this; - mfglayers.forEach(function(mfglayer: ManufacturingLayer, index: number) { - ref.__svgData.set(mfglayer.name, mfglayer.exportToSVG()); - mfglayer.flushData(); - }); - } - - /** - * Generates all the edge cuts - * @returns {void} - * @memberof CNCGenerator - */ - generateEdgeLayers(): void { - // TODO: Replace with something that does not - // simply generate a rectangle the dimensions of the device - - const topleft = new paper.Point(0, 0); - const bottomright = new paper.Point(this.__device.getXSpan(), this.__device.getYSpan()); - const edge = new paper.Path.Rectangle(topleft, bottomright); - const mfglayer = new ManufacturingLayer("UniversalEdge"); - mfglayer.addFeature(edge); - const ref = this; - ref.__svgData.set(mfglayer.name, mfglayer.exportToSVG()); - mfglayer.flushData(); - } - - /** - * Sets the device the CNCGenerator needs to work of - * @param {Device} currentDevice - * @returns {void} - * @memberof CNCGenerator - */ - setDevice(currentDevice: Device): void { - this.__device = currentDevice; - console.log("Currentdevice:", currentDevice); - } - - /** - * Flush all the data - * @returns {void} - * @memberof CNCGenerator - */ - flushData(): void { - this.__svgData.clear(); - } -} diff --git a/src/app/manufacturing/depthFeatureMap.ts b/src/app/manufacturing/depthFeatureMap.ts deleted file mode 100644 index 82ff1eca..00000000 --- a/src/app/manufacturing/depthFeatureMap.ts +++ /dev/null @@ -1,58 +0,0 @@ -/** - * Depth feature map class - */ -export default class DepthFeatureMap { - private __name: string; - __depthMap: Map; - - /** - * Default Constructor for DepthFeatureMap object. - * @param {string} name - */ - constructor(name: string) { - this.__name = name; - this.__depthMap = new Map(); - } - - /** - * Add feature to the object - * @param {number} depth Value of depth - * @param {*} featureref - * @memberof DepthFeatureMap - * @returns {void} - */ - addFeature(depth: number, featureref: any): void { - if (this.__depthMap.has(depth)) { - // Get the array stored for the depth - const features = this.__depthMap.get(depth); - if (features != undefined) features.push(featureref); - // this.__depthMap.set(depth, features); - } else { - const features = []; - features.push(featureref); - this.__depthMap.set(depth, features); - } - } - - /** - * Gets depth - * @returns {Array} Returns all the depth - * @memberof DepthFeatureMap - */ - getDepths(): IterableIterator { - return this.__depthMap.keys(); - } - - /** - * Gets features for a certain depth - * @param {*} depth - * @returns {Array} Returns the feature of the depth - * @memberof DepthFeatureMap - */ - getFeaturesAtDepth(depth: number): Array { - if (this.__depthMap.has(depth)) { - return this.__depthMap.get(depth) as Array; - } - throw new Error("Could not find features at Depth: " + depth); - } -} diff --git a/src/app/manufacturing/laserCuttingGenerator.ts b/src/app/manufacturing/laserCuttingGenerator.ts deleted file mode 100644 index 9d6a5729..00000000 --- a/src/app/manufacturing/laserCuttingGenerator.ts +++ /dev/null @@ -1,263 +0,0 @@ -import ManufacturingLayer from "./manufacturingLayer"; -import DepthFeatureMap from "./depthFeatureMap"; -import Device from "../core/device"; -import { ComponentAPI } from "@/componentAPI"; -import Layer from "../core/layer"; -import Feature from "../core/feature"; -import { LogicalLayerType } from "../core/init"; -import paper from "paper"; -import { ViewManager } from ".."; - -/** - * Lasser Cutting Generator object - */ -export default class LaserCuttingGenerator { - private __device: Device; - private __viewManagerDelegate: ViewManager; - - private __svgData: Map; - - /** - * Default Constructor for the laser cutting generator object - * @param {Device} device Device object - * @param {*} viewManagerDelegate - */ - constructor(device: Device, viewManagerDelegate: ViewManager) { - this.__device = device; - this.__viewManagerDelegate = viewManagerDelegate; - - this.__svgData = new Map(); - } - - /** - * Gets the SVG data - * @returns Returns the SVG data - * @memberof LaserCuttingGenerator - */ - getSVGOutputs(): Map { - return this.__svgData; - } - - /** - * Generate the port layers - * @memberof LaserCuttingGenerator - * @returns {void} - */ - generatePortLayers(): void { - - console.log("Port layers called and not executed, functionality moved to generateDepthLayers"); - } - - /** - * Generates separate mfglayers and svgs for each of the depth layers - * @memberof LaserCuttingGenerator - * @returns {void} - */ - generateDepthLayers(): void { - // Generate a manufacturing layer for each logical layer, - // substrate, depth combination in device - // and output to svg - - const layers: Array = this.__device.layers; - - const mfglayers: Array = []; - let isControl: boolean = false; - - const manufacturingLayerMap: Map = new Map(); - for (const i in layers) { - const layer: Layer = layers[i]; - - const features: { [index: string]: Feature } = layer.features; - - if (layer.type === LogicalLayerType.CONTROL) { - isControl = true; - } - - for (const key in features) { - const feature: Feature = features[key]; - - let manufacturingLayerName: string; - if (feature.manufacturingInfo.substrate !== null) { - manufacturingLayerName = - feature.manufacturingInfo.modifier + - "_" + - feature.manufacturingInfo.layertype + - "_" + - feature.manufacturingInfo.substrate.toString() + - "_" + - feature.manufacturingInfo.depth; - } else { - throw new Error("Manufacturing layer name failed to be generated"); - } - - if (manufacturingLayerMap.has(manufacturingLayerName)) { - const manufacturingLayer: ManufacturingLayer | undefined = manufacturingLayerMap.get(manufacturingLayerName); - let issuccessful: boolean; - if (manufacturingLayer != undefined) { - issuccessful = manufacturingLayer.addFeature(this.__viewManagerDelegate.view.getRenderedFeature(feature.ID)); - if (!issuccessful) console.error("Could not find the feature for the corresponding id: " + feature.ID); - manufacturingLayerMap.set(manufacturingLayerName, manufacturingLayer); - } else { - throw new Error("manufacturingLayer undefined"); - } - } else { - const odd: number = feature.manufacturingInfo.substrate % 2; - let flip: boolean = false; - if (odd == 1) flip = true; - const manufacturingLayer = new ManufacturingLayer(manufacturingLayerName, flip); - const issuccessful: boolean = manufacturingLayer.addFeature(this.__viewManagerDelegate.view.getRenderedFeature(feature.ID)); - if (!issuccessful) console.error("Could not find the feature for the corresponding id: " + feature.ID); - manufacturingLayerMap.set(manufacturingLayerName, manufacturingLayer); - } - } - } - - manufacturingLayerMap.forEach((manufacturingLayer, manufacturingLayerName) => { - if (manufacturingLayer.flip) { - manufacturingLayer.flipX(); - } - mfglayers.push(manufacturingLayer); - }); - - console.log("XY Manufacturing Layers:", mfglayers); - const ref = this; - mfglayers.forEach(function(mfglayer: ManufacturingLayer, index: number) { - ref.__svgData.set(mfglayer.name, mfglayer.exportToSVG()); - mfglayer.flushData(); - }); - } - - /** - * Generates all the edge cuts - * @memberof LaserCuttingGenerator - * @returns {void} - */ - generateEdgeLayers(): void { - // TODO: Replace with something that does not - // simply generate a rectangle the dimensions of the device - - const topleft = new paper.Point(0, 0); - const bottomright = new paper.Point(this.__device.getXSpan(), this.__device.getYSpan()); - const edge = new paper.Path.Rectangle(topleft, bottomright); - const mfglayer = new ManufacturingLayer("UniversalEdge"); - mfglayer.addFeature(edge); - const ref = this; - ref.__svgData.set(mfglayer.name, mfglayer.exportToSVG()); - mfglayer.flushData(); - } - - /** - * Sets the device the CNCGenerator needs to work of - * @param {Device} currentDevice - * @memberof LaserCuttingGenerator - * @returns {void} - */ - setDevice(currentDevice: Device): void { - this.__device = currentDevice; - console.log("Currentdevice:", currentDevice); - } - - /** - * Flush all the data - * @memberof LaserCuttingGenerator - * @returns {void} - */ - flushData(): void { - this.__svgData.clear(); - } - - /** - * Generates all the glue burn off layers necessary for the valves - * @memberof LaserCuttingGenerator - * @returns {void} - */ - generateInverseControlLayers(): void { - console.log("Generating inverse layers"); - const layers: Array = this.__device.layers; - - const mfglayers: Array = []; - - let isControl: boolean = false; - const manufacturingLayerMap: Map = new Map(); - for (const i in layers) { - const layer: Layer = layers[i]; - - const features: { [index: string]: Feature } = layer.features; - - if (layer.type == LogicalLayerType.CONTROL) { - isControl = true; - } - - // Add logic to generate the here to check if its control... - if (isControl) { - // Do the actual feature generation part here - for (const key in features) { - const feature: Feature = features[key]; - // TODO: Include fabtype check also - const type: string = feature.getType(); - - /* - Check if type has an inverse layer - */ - - // Skip the EDGE features - if (type === "EDGE") { - continue; - } - - if (ComponentAPI.hasInverseRenderLayer(type)) { - let manufacturingLayerName: string; - console.log("TYPE: ",feature.type); - console.log("MANINFO: ", feature.manufacturingInfo); - if (feature.manufacturingInfo.substrate !== null) { - manufacturingLayerName = - "INVERSE" + - "_" + - feature.manufacturingInfo.layertype + - "_" + - feature.manufacturingInfo.substrate.toString() + - "_" + - feature.manufacturingInfo.depth; - } else { - throw new Error("Manufacturing layer name failed to be generated"); - } - console.log(manufacturingLayerName); - if (manufacturingLayerMap.has(manufacturingLayerName)) { - const manufacturingLayer: ManufacturingLayer | undefined = manufacturingLayerMap.get(manufacturingLayerName); - let issuccessful: boolean; - if (manufacturingLayer != undefined) { - issuccessful = manufacturingLayer.generateFeatureRender(feature, "INVERSE"); - if (!issuccessful) console.error("Could not find the feature for the corresponding id: " + feature.ID); - manufacturingLayerMap.set(manufacturingLayerName, manufacturingLayer); - } else { - throw new Error("manufacturingLayer undefined"); - } - } else { - const manufacturingLayer = new ManufacturingLayer(manufacturingLayerName); - const issuccessful: boolean = manufacturingLayer.generateFeatureRender(feature, "INVERSE"); - if (!issuccessful) console.error("Could not find the feature for the corresponding id: " + feature.ID); - manufacturingLayerMap.set(manufacturingLayerName, manufacturingLayer); - } - /* - If the type has an inverse layer, then generate the inverse feature render - and throw it into the manufacturing layer. - */ - } - } - isControl = false; - } - } - - manufacturingLayerMap.forEach((manufacturingLayer, manufacturingLayerName) => { - mfglayers.push(manufacturingLayer); - }); - - console.log("Inverse Control Manufacturing Layers:", mfglayers); - - const ref = this; - mfglayers.forEach(function(mfglayer: ManufacturingLayer, index: number) { - ref.__svgData.set(mfglayer.name, mfglayer.exportToSVG()); - mfglayer.flushData(); - }); - } -} diff --git a/src/app/manufacturing/manufacturingInfo.ts b/src/app/manufacturing/manufacturingInfo.ts deleted file mode 100644 index c0163e3f..00000000 --- a/src/app/manufacturing/manufacturingInfo.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { LogicalLayerType } from "../core/init"; - -export enum DFMType { - EDGE = "EDGE", - XYZ = "XYZ", - XY = "XY", - Z = "Z" -} - -/** - * Type which contains information for manufacturing svg production - * @param {DFMType} fabtype Type of fabrication - * @param {LogicalLayerType | null} layertype Type of layer on which the feature sits - * @param {string} rendername Key which accesses the z-offset-key and substrate--offset - * @param {string} z-offset-key Key which corresponds to the property representing height of the feature - * @param {string} substrate_offset String represented value which represent how this substrate relates to the FLOW substrate - */ -export type ManufacturingInfo = { - fabtype: DFMType; - layertype: LogicalLayerType | null; - rendername: string; - z_offset_key: string; - depth: number; - substrate_offset: string; - substrate: number | null; - modifier: string | null; -}; diff --git a/src/app/manufacturing/manufacturingLayer.ts b/src/app/manufacturing/manufacturingLayer.ts deleted file mode 100644 index ca230d17..00000000 --- a/src/app/manufacturing/manufacturingLayer.ts +++ /dev/null @@ -1,152 +0,0 @@ -import paper from "paper"; -import * as FeatureRenderer2D from "../view/render2D/featureRenderer2D"; -import Registry from "../core/registry"; -import Feature from "../core/feature"; -import Device from "../core/device"; -import { PaperView } from ".."; -import { ToolPaperObject } from "../core/init"; - -/** - * Manufacturing Layer class - */ -export default class ManufacturingLayer { - __features: Array; - __name: string; - __paperGroup: paper.Group; - __flip: boolean; - - /** - * Default Constructor for the Manufacturing Layer - * @param {String} name Name of the field - */ - constructor(name: string, flip = false) { - this.__features = []; - this.__name = name; - this.__paperGroup = new paper.Group(); - this.__flip = flip; - } - - /** - * Returns the name field - * @return {String} Returns the name of the field - * @memberof ManufacturingLayer - */ - get name(): string { - return this.__name; - } - - /** - * Returns the flip property - * @return {boolean} Returns a boolean representing whether the manufacturing layer should be flipped - * @memberof ManufacturingLayer - */ - get flip(): boolean { - return this.__flip; - } - - /** - * Adds a feature to the manufacturing layer - * @param {Feature} feature Feature to add to the layer - * @memberof ManufacturingLayer - * @returns {boolean} - */ - addFeature(feature: ToolPaperObject): boolean { - if (feature === null || undefined === feature) { - return false; - } - const copy: ToolPaperObject = feature.clone(); - console.log("Copied feature", copy); - this.__features.push(copy); - - this.__paperGroup.addChild(copy); - return true; - } - - /** - * Generates the paperjs render for a feature that has no render displayed on the canvas - * and hence cannot get the render out of display set. - * @param feature - * @param renderkey - * @returns {boolean} - * @memberof ManufacturingLayer - */ - generateFeatureRender(feature: Feature, renderkey: string | null): boolean { - console.log("Generating Render for invisible feature", feature); - - const render: ToolPaperObject = FeatureRenderer2D.renderFeature(feature, renderkey); - this.__features.push(render); - - this.__paperGroup.addChild(render); - return true; - } - - /** - * Flips the manufacturing layer in X-Axis - * @memberof ManufacturingLayer - * @returns {void} - */ - flipX(): void { - // console.warn("Implement method to flip the the group"); - /* - Step 2 - Flip the whole godamn thing - */ - const currentDevice: Device | null = Registry.currentDevice; - if (currentDevice !== null) { - const yspan = currentDevice.getYSpan(); - const xspan = currentDevice.getXSpan(); - - console.log("Flipping stuff:", xspan, yspan); - - const center = new paper.Point(xspan / 2, yspan / 2); - - this.__paperGroup.scale(-1, 1, center); - } - } - - /** - * Returns the SVG text - * @return {string} - * @memberof ManufacturingLayer - */ - exportToSVG(): string { - const currentDevice: Device | null = Registry.currentDevice; - if (currentDevice !== null) { - const yspan = currentDevice.getYSpan(); - const xspan = currentDevice.getXSpan(); - let svgtext = this.__paperGroup.exportSVG({ asString: true }); - svgtext = ManufacturingLayer.generateSVGTextPrepend(xspan, yspan) + svgtext + ManufacturingLayer.generateSVGTextAppend(); - return svgtext; - } else { - throw new Error("Registry.currentDevice is null"); - } - } - - /** - * @memberof ManufacturingLayer - * @returns {void} - */ - flushData(): void { - this.__paperGroup.removeChildren(); - } - - /** - * Generates the SVG Prepend - * @param {number} xspan - * @param {number} yspan - * @return {string} - * @memberof ManufacturingLayer - */ - static generateSVGTextPrepend(xspan: number, yspan: number): string { - const text = ``; - return text; - } - - /** - * Generates the SVG Append - * @return {string} - * @memberof ManufacturingLayer - */ - static generateSVGTextAppend(): string { - return ""; - } -} diff --git a/src/app/plugin/dafdPlugin.ts b/src/app/plugin/dafdPlugin.ts deleted file mode 100644 index a9104b48..00000000 --- a/src/app/plugin/dafdPlugin.ts +++ /dev/null @@ -1,127 +0,0 @@ -import { Registry } from "../index"; -import Connection from "../core/connection"; -import Feature from "../core/feature"; -import ChannelTool from "../view/tools/channelTool"; -import ComponentPort from "../core/componentPort"; - -export default class DAFDPlugin { - static fixLayout(params: { [k: string]: any }): void { - // Update Params - let channelid; - const orificeSize = params.orificeSize; - const orificeLength = params.orificeLength; - const oilInputWidth = params.oilInputWidth; - const waterInputWidth = params.waterInputWidth; - const outputWidth = params.outputWidth; - const outputLength = params.outputLength; - const height = params.height; - - // Load up all the components and change their positions based on the component dimensions - const dropgen = Registry.currentDevice?.getComponentByName("DropletGen_1"); - const port_in = Registry.currentDevice?.getComponentByName("Port_in"); - const port_oil1 = Registry.currentDevice?.getComponentByName("Port_oil1"); - const port_oil2 = Registry.currentDevice?.getComponentByName("Port_oil2"); - const port_out = Registry.currentDevice?.getComponentByName("Port_out"); - - const transition_in = Registry.currentDevice?.getFeatureByName("Transition_3"); - const transition_oil1 = Registry.currentDevice?.getFeatureByName("Transition_6"); - const transition_oil2 = Registry.currentDevice?.getFeatureByName("Transition_5"); - const transition_out = Registry.currentDevice?.getFeatureByName("Transition_4"); - - // Update all the droplet generator params - dropgen?.updateParameter("orificeSize", orificeSize); - dropgen?.updateParameter("orificeLength", orificeLength); - dropgen?.updateParameter("oilInputWidth", oilInputWidth); - dropgen?.updateParameter("waterInputWidth", waterInputWidth); - dropgen?.updateParameter("outputWidth", outputWidth); - dropgen?.updateParameter("outputLength", outputLength); - dropgen?.updateParameter("height", height); - - // Update the transitions - transition_out?.updateParameter("cw2", outputWidth); - transition_in?.updateParameter("cw2", waterInputWidth); - transition_oil1?.updateParameter("cw2", oilInputWidth); - transition_oil2?.updateParameter("cw2", oilInputWidth); - - const componentports = dropgen?.ports; - console.log("component ports:", componentports); - // Draw the channels - let startpoint; - let endpoint; - let cp; - - // Align ports to the droplet generator - const dxpos = dropgen?.getPosition()[0]; - const xpos = dxpos! + oilInputWidth / 2; - let ypos = port_oil1?.getCenterPosition()[1]; - port_oil1?.updateComponentPosition([xpos, ypos!]); - ypos = port_oil2?.getCenterPosition()[1]; - port_oil2?.updateComponentPosition([xpos, ypos!]); - - // Moving teh transistions to align with droplet generators - ypos = port_oil1?.getValue("position")[1]; - transition_oil1?.updateParameter("position", [xpos, ypos]); - ypos = port_oil2?.getValue("position")[1]; - transition_oil2?.updateParameter("position", [xpos, ypos]); - const inpos = port_in?.getValue("position"); - const outpos = port_out?.getValue("position"); - transition_in?.updateParameter("position", inpos); - transition_out?.updateParameter("position", outpos); - - // Input Channel - startpoint = port_in?.getCenterPosition(); - cp = componentports?.get("4"); - endpoint = ComponentPort.calculateAbsolutePosition(cp!, dropgen!); - console.log("endpoint", endpoint); - let newChannel = ChannelTool.createChannel(startpoint, endpoint, ("RoundedChannel" as unknown) as null, ("Basic" as unknown) as null); - channelid = (newChannel as any).getID(); - - //Registry.currentLayer.addFeature(newChannel); - Registry.viewManager?.addFeature(newChannel); - - newChannel = Registry.currentDevice!.getFeatureByID(channelid); - newChannel.updateParameter("channelWidth", waterInputWidth); - - // oil top Channel - startpoint = port_oil1?.getCenterPosition(); - cp = componentports?.get("1"); - endpoint = ComponentPort.calculateAbsolutePosition(cp!, dropgen!); - console.log("endpoint", endpoint); - newChannel = ChannelTool.createChannel(startpoint, endpoint, ("RoundedChannel" as unknown) as null, ("Basic" as unknown) as null); - channelid = (newChannel as any).getID(); - - //Registry.currentLayer.addFeature(newChannel); - Registry.viewManager?.addFeature(newChannel); - newChannel = Registry.currentDevice!.getFeatureByID(channelid); - newChannel.updateParameter("channelWidth", oilInputWidth); - - // output Channel - startpoint = port_out?.getCenterPosition(); - cp = componentports?.get("2"); - endpoint = ComponentPort.calculateAbsolutePosition(cp!, dropgen!); - console.log("endpoint", endpoint); - newChannel = ChannelTool.createChannel(startpoint, endpoint, ("RoundedChannel" as unknown) as null, ("Basic" as unknown) as null); - channelid = (newChannel as any).getID(); - - //Registry.currentLayer.addFeature(newChannel); - Registry.viewManager?.addFeature(newChannel); - - newChannel = Registry.currentDevice!.getFeatureByID(channelid); - newChannel.updateParameter("channelWidth", outputWidth); - - // oil bottom Channel - startpoint = port_oil2?.getCenterPosition(); - cp = componentports?.get("3"); - console.log("cp", cp); - endpoint = ComponentPort.calculateAbsolutePosition(cp!, dropgen!); - console.log("endpoint", endpoint); - newChannel = ChannelTool.createChannel(startpoint, endpoint, ("RoundedChannel" as unknown) as null, ("Basic" as unknown) as null); - channelid = (newChannel as any).getID(); - - //Registry.currentLayer.addFeature(newChannel); - Registry.viewManager?.addFeature(newChannel); - - newChannel = Registry.currentDevice!.getFeatureByID(channelid); - newChannel.updateParameter("channelWidth", oilInputWidth); - } -} diff --git a/src/app/utils/componentUtils.ts b/src/app/utils/componentUtils.ts deleted file mode 100644 index 458a8552..00000000 --- a/src/app/utils/componentUtils.ts +++ /dev/null @@ -1,26 +0,0 @@ -import Registry from "@/app/core/registry"; -import { ComponentAPI } from "@/componentAPI"; - -export default class ComponentUtils { - constructor() {} - - static getFeatureFromID(featureid: string) { - return Registry.currentDevice!.getFeatureByID(featureid); - } - - static getRenderedFeature(featureid: string) { - return Registry.viewManager!.view.getRenderedFeature(featureid); - } - - static generateDeviceName(type: string): string { - return Registry.currentDevice!.generateNewName(type); - } - - static getDeviceLayers() { - return Registry.currentDevice!.layers; - } - - static getDeviceLayerFromID(featureid: string) { - return Registry.currentDevice!.getLayerFromFeatureID(featureid); - } -} diff --git a/src/app/utils/connectionUtils.ts b/src/app/utils/connectionUtils.ts deleted file mode 100644 index 7f31b080..00000000 --- a/src/app/utils/connectionUtils.ts +++ /dev/null @@ -1,15 +0,0 @@ -import Registry from "@/app/core/registry"; -import { ComponentAPI } from "@/componentAPI"; - -export default class ConnectionUtils { - constructor() {} - - - static getDefinition(stringname: string) { - return ComponentAPI.getDefinition("Connection"); - } - - static getFeatureFromID(featureid: string) { - return Registry.currentDevice!.getFeatureByID(featureid); - } -} diff --git a/src/app/utils/cookieUtils.ts b/src/app/utils/cookieUtils.ts deleted file mode 100644 index 5f780445..00000000 --- a/src/app/utils/cookieUtils.ts +++ /dev/null @@ -1,21 +0,0 @@ -export function setCookie(cname: string, cvalue: string, exdays: number): void { - const d = new Date(); - d.setTime(d.getTime() + exdays * 24 * 60 * 60 * 1000); - const expires = "expires=" + d.toUTCString(); - document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/"; -} - -export function getCookie(cname: string): string { - const name = cname + "="; - const ca = document.cookie.split(";"); - for (let i = 0; i < ca.length; i++) { - let c = ca[i]; - while (c.charAt(0) === " ") { - c = c.substring(1); - } - if (c.indexOf(name) === 0) { - return c.substring(name.length, c.length); - } - } - return ""; -} diff --git a/src/app/utils/deviceUtils.ts b/src/app/utils/deviceUtils.ts deleted file mode 100644 index c1dbbed8..00000000 --- a/src/app/utils/deviceUtils.ts +++ /dev/null @@ -1,27 +0,0 @@ -import Registry from "@/app/core/registry"; -import Layer from "../core/layer"; - -export default class DeviceUtils { - static __nameMap = new Map(); - - static addLayer(layer: Layer, index: number): void { - Registry.viewManager!.addLayer(layer, index); - } - - /** - * Generates a new new name for the type, use this to autogenerate the names for components that are typespecific - * @param {string} type - * @return {string} - * @memberof Device - */ - static generateNewName(type: string): string { - let value = DeviceUtils.__nameMap.get(type); - if (value != undefined) { - this.__nameMap.set(type, value + 1); - return type + "_" + String(value + 1); - } else { - this.__nameMap.set(type, 1); - return type + "_1"; - } - } -} diff --git a/src/app/utils/exportUtils.ts b/src/app/utils/exportUtils.ts deleted file mode 100644 index 7f4b729e..00000000 --- a/src/app/utils/exportUtils.ts +++ /dev/null @@ -1,149 +0,0 @@ -import ViewManager from "@/app/view/viewManager"; - -import { - ConnectionTargetInterchangeV1, - GeometryElementInterchangeV1_2, - InterchangeV1_2 - // DeviceInterchangeV1, - // LayerInterchangeV1, - // RenderLayerInterchangeV1, - // FeatureInterchangeV0, - // ComponentInterchangeV1, - // ConnectionInterchangeV1, - // ComponentPortInterchangeV1, - // LogicalLayerType -} from "@/app/core/init"; -import ConnectionTarget from "../core/connectionTarget"; -import GeometryElement from "../core/geometryElement"; - -export class SerializationError { - /** - * Error message for the user. - * - * @type {string} - * @memberof SerializationError - */ - public message: string; - - /** - * The element that caused the error. - * TBD on how ot use this in the future. - * @type {*} - * @memberof SerializationError - */ - public element: string; - - /** - * The JSON data that was being processed when the error occurred. - * - * @type {string} - * @memberof SerializationError - */ - public jsonData: string; - - /** - * Creates an instance of SerializationError. - * @param {string} message - * @param {string} element - * @param {string} jsonData - * @memberof SerializationError - */ - constructor(message: string, element: string, jsonData: string) { - this.message = message; - this.element = element; - this.jsonData = jsonData; - } - - /** - * Converts the error to a string. - * suitable for display to the user. or in a log file. - * - * @returns {string} - * @memberof SerializationError - */ - toText(): string { - let ret = `Error: ${this.message}\n`; - ret += `Element: ${this.element}\n`; - ret += "JSON Data:\n"; - ret += "\`\`\`\n"; - ret += this.jsonData; - ret += "\n\`\`\`\n"; - - return ret; - } -} - - -export default class ExportUtils { - - /** - * Converts a device to interchange format. - * - * @static - * @param {ViewManager} viewManagerDelegate - * @returns {InterchangeV1_2} - * @memberof ExportUtils - */ - static toInterchangeV1_2(viewManagerDelegate: ViewManager, errorList:SerializationError[]): InterchangeV1_2 { - if(viewManagerDelegate.currentDevice === null) { - throw new Error("No device selected"); - } - let renderLayers = []; - if (viewManagerDelegate === null) throw new Error("Registry or viewManager not initialized"); - for (let i = 0; i < viewManagerDelegate.renderLayers.length; i++) { - renderLayers.push(viewManagerDelegate.renderLayers[i].toInterchangeV1()); - } - const device = viewManagerDelegate.currentDevice.toInterchangeV1(errorList); - - const valvemap = {}; - const valvetypemap = {}; - - - const newScratch: InterchangeV1_2 = { - name: device.name, - params: device.params, - renderLayers: renderLayers, - layers: device.layers, - groups: device.groups, - components: device.components, - connections: device.connections, - valves: device.valves, - features: ExportUtils.featuresToInterchangeV1_2(viewManagerDelegate.currentDevice.parchmintFeatures) , - version: "1.2" - }; - - return newScratch; - } - - /** - * Converts a list of features to interchange format. - * @static - * @param {Array} featuresGeometries - * @returns {Array} - * @memberof ExportUtils - */ - static featuresToInterchangeV1_2(featuresGeometries: Array): Array { - let features: Array = []; - featuresGeometries.forEach(feature => { - features.push(feature.toInterchageV1_2()); - }); - return features; - } - - /** - * Converts a device to interchange format. - * - * @static - * @param {ConnectionTarget} target - * @returns {ConnectionTargetInterchangeV1} - * @memberof ExportUtils - */ - static toConnectionTargetInterchangeV1(target: ConnectionTarget): ConnectionTargetInterchangeV1{ - const ret: ConnectionTargetInterchangeV1 = { - component: target.component.id, - port: target.portLabel - }; - return ret; - } -} - diff --git a/src/app/utils/featureUtils.ts b/src/app/utils/featureUtils.ts deleted file mode 100644 index 42fd8df6..00000000 --- a/src/app/utils/featureUtils.ts +++ /dev/null @@ -1,47 +0,0 @@ -import Registry from "@/app/core/registry"; -import Feature from "@/app/core/feature"; -import Layer from "@/app/core/layer"; -import RenderLayer from "@/app/view/renderLayer"; -import { LogicalLayerType } from "@/app/core/init"; - -export default class FeatureUtils { - /** - * Determines substrate from layer index and susbtrate offset - * @return {number} - * @memberof FeatureUtils - */ - static setSubstrate(feature: Feature, offset: string): number { - let substrate: number; - let layer: Layer | null = feature.layer; - if (layer === null) { - throw new Error("Layer never set for feature " + feature.ID); - } else if (Registry.currentDevice === null) { - throw new Error("Current device has not been set in registry"); - } - - if (layer.type == LogicalLayerType.FLOW) { - if (offset.includes("-")) { - substrate = ~~(Registry.currentDevice.layers.indexOf(layer) / 3) - parseInt(offset); - } else { - substrate = ~~(Registry.currentDevice.layers.indexOf(layer) / 3) + parseInt(offset); - } - } else if (layer.type == LogicalLayerType.CONTROL) { - if (offset.includes("-")) { - substrate = ~~(Registry.currentDevice.layers.indexOf(layer) / 3) - parseInt(offset); - } else if (offset != "0") { - substrate = ~~(Registry.currentDevice.layers.indexOf(layer) / 3) + parseInt(offset); - } else { - substrate = ~~(Registry.currentDevice.layers.indexOf(layer) / 3) + 1; - } - } else if (layer.type == LogicalLayerType.INTEGRATION) { - if (offset.includes("-")) { - substrate = ~~(Registry.currentDevice.layers.indexOf(layer) / 3) - parseInt(offset); - } else { - substrate = ~~(Registry.currentDevice.layers.indexOf(layer) / 3) + parseInt(offset); - } - } else { - throw new Error("Layer type" + layer.type + "not recognized"); - } - return substrate; - } -} diff --git a/src/app/utils/geometryUtils.ts b/src/app/utils/geometryUtils.ts deleted file mode 100644 index 83e59bc4..00000000 --- a/src/app/utils/geometryUtils.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* Returns the the radian value of the specified degrees in the range of (-PI, PI] */ -export function degToRad(degrees: number): number { - const res = (degrees / 180) * Math.PI; - return res; -} - -/* Returns the radian value of the specified radians in the range of [0,360), to a precision of four decimal places. */ -export function radToDeg(radians: number): number { - const res = (radians * 180) / Math.PI; - return res; -} - -export function computeAngleFromPoints(start: number[], end: number[]): number { - const dX = end[0] - start[0]; - const dY = end[1] - start[1]; - return computeAngle(dX, dY); -} - -export function computeAngle(dX: number, dY: number): number { - return radToDeg(Math.atan2(dY, dX)); -} - -export function computeDistanceBetweenPoints(start: number[], end: number[]): number { - return computeDistance(end[0] - start[0], end[1] - start[1]); -} - -export function computeDistance(dX: number, dY: number): number { - return Math.sqrt(Math.pow(dX, 2) + Math.pow(dY, 2)); -} - -export function computeEndPoint(start: number[], angle: number, length: string | number) { - length = parseFloat(length as string); - const rad = degToRad(angle); - const dX = length * Math.cos(rad); - const dY = length * Math.sin(rad); - return [start[0] + dX, start[1] + dY]; -} diff --git a/src/app/utils/htmlUtils.ts b/src/app/utils/htmlUtils.ts deleted file mode 100644 index f8afe530..00000000 --- a/src/app/utils/htmlUtils.ts +++ /dev/null @@ -1,49 +0,0 @@ -export function removeClass(el: HTMLElement, className: string): void { - if (el.classList) el.classList.remove(className); - else el.className = el.className.replace(new RegExp("(^|\\b)" + className.split(" ").join("|") + "(\\b|$)", "gi"), " "); -} - -export function addClass(el: HTMLElement, className: string): void { - if (el.classList) el.classList.add(className); - else el.className += " " + className; -} - -// From http://stackoverflow.com/questions/8869403/drag-drop-json-into-chrome -export function DnDFileController(this: any, selector: string, onDropCallback: (files: FileList, e: unknown) => any): void { - const el_ = document.querySelector(selector); - this.dragenter = function(e: DragEvent) { - e.stopPropagation(); - e.preventDefault(); - el_?.classList.add("dropping"); - }; - - this.dragover = function(e: DragEvent) { - e.stopPropagation(); - e.preventDefault(); - }; - - this.dragleave = function(e: DragEvent) { - e.stopPropagation(); - e.preventDefault(); - // el_.classList.remove('dropping'); - }; - - this.drop = function(e: DragEvent) { - e.stopPropagation(); - e.preventDefault(); - - el_?.classList.remove("dropping"); - - onDropCallback(e.dataTransfer?.files!, e); - }; - - el_?.addEventListener("dragenter", this.dragenter, false); - el_?.addEventListener("dragover", this.dragover, false); - el_?.addEventListener("dragleave", this.dragleave, false); - el_?.addEventListener("drop", this.drop, false); -} - -export function setButtonColor(button: HTMLButtonElement, color: string, text: string): void { - button.style.background = color; - button.style.color = text; -} diff --git a/src/app/utils/ioUtils.ts b/src/app/utils/ioUtils.ts deleted file mode 100644 index 6bfd0f92..00000000 --- a/src/app/utils/ioUtils.ts +++ /dev/null @@ -1,43 +0,0 @@ -export function mapToJson(map: Map) { - console.log("map to json"); - const object: { [k: string]: any } = {}; - for (const [k, v] of map) { - // We don’t escape the key '__proto__' - // which can cause problems on older engines - object[k] = v; - } - return object; -} - -export function jsonToMap(jsonStr: { [k: string]: any }) { - console.log("json to map"); - const ret = new Map(); - for (const key in jsonStr) { - const value = jsonStr[key]; - console.log("Setting:", key, value); - ret.set(key, value); - } - return ret; -} - -function fixDeviceDimensionParams(json: { [k: string]: any }) { - if (Object.prototype.hasOwnProperty.call(json, "params")) { - if (Object.prototype.hasOwnProperty.call(json.params, "width")) { - const xspan = json.params.width; - json.params.xspan = xspan; - delete json.params.width; - console.warn("Fixed issue with incorrect device xspan param"); - } - if (Object.prototype.hasOwnProperty.call(json.params, "length")) { - const yspan = json.params.length; - json.params.yspan = yspan; - delete json.params.length; - console.warn("Fixed issue with incorrect device yspan param"); - } - } -} - -export function sanitizeV1Plus(jsonstr: { [k: string]: any }): void { - fixDeviceDimensionParams(jsonstr); - // TODO: add other proceses -} diff --git a/src/app/utils/linkedList.ts b/src/app/utils/linkedList.ts deleted file mode 100644 index 59edafd1..00000000 --- a/src/app/utils/linkedList.ts +++ /dev/null @@ -1,117 +0,0 @@ -export default class LinkedList { - head: Node | null; - tail: Node | null; - count: number; - current: Node | null; - - constructor() { - this.head = null; - this.tail = null; - this.count = 0; - this.current = null; - } - - currentData() { - return this.current?.data; - } - - removeCurrent(): void { - const prev = this.current!.prev; - const next = this.current!.next; - - prev!.next = next; - next!.prev = prev; - } - - removeNode(node: { [k: string]: any }): void { - const cnode = this.head; - if (node.id === cnode?.id) { - // remove the node - const prev = cnode!.prev; - const next = cnode!.next; - - prev!.next = next; - if (next) { - next.prev = prev; - } - } else { - let nextnode = LinkedList.getNextNode(cnode!); - while (nextnode) { - if (nextnode.id === node.id) { - // remove the node - const prev = nextnode.prev; - const next = nextnode.next; - - prev!.next = next; - if (next) { - next.prev = prev; - } - break; - } else { - nextnode = LinkedList.getNextNode(nextnode); - } - } - } - this.count--; - } - - get length() { - return this.count; - } - - push(data: { [k: string]: any }): void { - // Incase its the first one - if (this.count === 0) { - const node = new Node(data); - this.head = node; - this.tail = node; - } else { - // Save the old head - const temp = this.head; - - // Set the new head - const node = new Node(data); - node.id = this.count; - - // Create new links - node.next = temp; - temp!.prev = node; - - this.head = node; - } - this.count++; - } - - getArray() { - const retarray = []; - retarray.push(this.head!.data); - let nextnode = LinkedList.getNextNode(this.head!); - while (nextnode) { - retarray.push(nextnode.data); - nextnode = LinkedList.getNextNode(nextnode); - } - return retarray; - } - - static getNextNode(node: Node) { - return node.next; - } - - static getPreviousNode(node: Node) { - return node.prev; - } -} - -class Node { - prev: Node | null; - data: any; - next: Node | null; - id: number; - - constructor(data: any) { - this.prev = null; - this.data = data; - this.next = null; - this.id = 0; - } -} diff --git a/src/app/utils/loadUtils.ts b/src/app/utils/loadUtils.ts deleted file mode 100644 index 166277dd..00000000 --- a/src/app/utils/loadUtils.ts +++ /dev/null @@ -1,741 +0,0 @@ -import Device from "@/app/core/device"; -import Layer from "@/app/core/layer"; -import Connection from "@/app/core/connection"; -import Component from "@/app/core/component"; -import Feature from "@/app/core/feature"; -import Params from "@/app/core/params"; -import RenderLayer from "@/app/view/renderLayer"; - -import CustomComponent from "@/app/core/customComponent"; -import ComponentPort from "@/app/core/componentPort"; -import { ComponentAPI } from "@/componentAPI"; -import MapUtils from "./mapUtils"; - -import ConnectionUtils from "@/app/utils/connectionUtils"; - -import { - InterchangeV1_2, - DeviceInterchangeV1, - LayerInterchangeV1, - RenderLayerInterchangeV1_2, - FeatureInterchangeV1_2, - ComponentInterchangeV1, - ConnectionInterchangeV1_2, - ComponentPortInterchangeV1, - LogicalLayerType, - ValveType, - DeviceInterchangeV1_1 -} from "@/app/core/init"; - -export default class LoadUtils { - constructor() {} - - static loadFromScratch(json: InterchangeV1_2): [Device, Array] { - const newDevice: Device = LoadUtils.loadDeviceFromInterchangeV1_2(json); - let newRenderLayers: Array = []; - if (json.renderLayers) { - for (let i = 0; i < json.renderLayers.length; i++) { - newRenderLayers.push(LoadUtils.loadRenderLayerFromInterchangeV1(json.renderLayers[i], newDevice)); - } - } else if (Object.prototype.hasOwnProperty.call(json, "layers")) { - for (let i = 0; i < json.layers.length; i++) { - newRenderLayers.push(LoadUtils.generateRenderLayerFromLayerInterchangeV1(json.layers[i], newDevice)); - } - } else { - newRenderLayers.push(new RenderLayer(newDevice.generateNewName("RenderLayerFlow"), newDevice.layers[0], LogicalLayerType.FLOW)); - newRenderLayers.push(new RenderLayer(newDevice.generateNewName("RenderLayerControl"), newDevice.layers[1], LogicalLayerType.CONTROL)); - newRenderLayers.push(new RenderLayer(newDevice.generateNewName("RenderLayerIntegration"), newDevice.layers[0], LogicalLayerType.INTEGRATION)); - } - - // Ensures that there are three layers per group - let layerGroups: Map = new Map(); - for (let i = 0; i < newDevice.layers.length; i++) { - if (layerGroups.has(newDevice.layers[i].group)) { - const currentVal = layerGroups.get(newDevice.layers[i].group); - if (currentVal) layerGroups.set(newDevice.layers[i].group, currentVal + 1); - } else { - layerGroups.set(newDevice.layers[i].group, 1); - } - } - - layerGroups.forEach((value, key) => { - const keyVal = parseInt(key, 10); - - if (value == 3) { - console.log("All layers accounted for in group " + key); - } else { - const layerTypes: Array = ["FLOW", "CONTROL", "INTEGRATION"]; - for (const i in json.layers) { - const index = layerTypes.indexOf(json.layers[i].type); - layerTypes.splice(index, 1); - } - console.log(layerTypes.length + " layers missing from group " + key + ", these will be generated"); - for (const j in layerTypes) { - const featuresToAdd = LoadUtils.generateMissingLayerFeaturesV1(json, layerTypes[j], key); - if (layerTypes[j] == "FLOW") { - const newLayer = new Layer({}, newDevice.generateNewName("LayerFlow"), LogicalLayerType.FLOW, key, newDevice); - for (const k in featuresToAdd) { - newLayer.features[featuresToAdd[k].ID] = featuresToAdd[k]; - } - newLayer.featureCount = featuresToAdd.length; - newDevice.addLayerAtIndex(newLayer, keyVal * 3); - newRenderLayers.splice(keyVal * 3, 0, new RenderLayer(newDevice.generateNewName("RenderLayerFlow"), newDevice.layers[keyVal * 3], LogicalLayerType.FLOW)); - } - else if (layerTypes[j] == "CONTROL") { - const newLayer = new Layer({}, newDevice.generateNewName("LayerControl"), LogicalLayerType.CONTROL, key, newDevice); - for (const k in featuresToAdd) { - newLayer.features[featuresToAdd[k].ID] = featuresToAdd[k]; - } - newLayer.featureCount = featuresToAdd.length; - newDevice.addLayerAtIndex(newLayer, keyVal * 3 + 1); - newRenderLayers.splice(keyVal * 3 + 1, 0, new RenderLayer(newDevice.generateNewName("RenderLayerControl"), newDevice.layers[keyVal * 3 + 1], LogicalLayerType.CONTROL)); - } - else if (layerTypes[j] == "INTEGRATION") { - const newLayer = new Layer({}, newDevice.generateNewName("LayerIntegration"), LogicalLayerType.INTEGRATION, key, newDevice); - for (const k in featuresToAdd) { - newLayer.features[featuresToAdd[k].ID] = featuresToAdd[k]; - } - newLayer.featureCount = featuresToAdd.length; - newDevice.addLayerAtIndex(newLayer, keyVal * 3 + 2); - newRenderLayers.splice(keyVal * 3 + 2, 0, new RenderLayer(newDevice.generateNewName("RenderLayerIntegration"), newDevice.layers[keyVal * 3 + 2], LogicalLayerType.INTEGRATION)); - } - } - } - }); - - //Updating cross-references - let features = newDevice.getAllFeaturesFromDevice(); - for (let i in features) { - const feature = features[i]; - if (feature.referenceID !== null) { - newDevice.updateObjectReference(feature.referenceID, feature.ID); - } - } - - return [newDevice, newRenderLayers]; - } - - static loadDeviceFromInterchangeV1_2(json: InterchangeV1_2): Device { - let newDevice: Device; - if (Object.prototype.hasOwnProperty.call(json, "params")) { - if (Object.prototype.hasOwnProperty.call(json.params, "width") && Object.prototype.hasOwnProperty.call(json.params, "length")) { - newDevice = new Device( - { - "x-span": json.params.width, - "y-span": json.params.length - }, - json.name - ); - } else { - newDevice = new Device( - { - "x-span": 135000, - "y-span": 85000 - }, - json.name - ); - } - } else { - console.warn("Could not find device params, using some default values for device size"); - newDevice = new Device( - { - width: 135000, - length: 85000 - }, - json.name - ); - } - - //Check if JSON has layers else mark - if (Object.prototype.hasOwnProperty.call(json, "layers")) { - for (const i in json.layers) { - newDevice.addLayer(LoadUtils.loadLayerFromInterchangeV1(json, json.layers[i], newDevice)); - } - } else { - //We need to add a default layer - let newlayer = new Layer({}, newDevice.generateNewName("LayerFlow"), LogicalLayerType.FLOW, "0", newDevice); - newDevice.addLayer(newlayer); - newlayer = new Layer({}, newDevice.generateNewName("LayerControl"), LogicalLayerType.CONTROL, "0", newDevice); - newDevice.addLayer(newlayer); - newlayer = new Layer({}, newDevice.generateNewName("LayerIntegration"), LogicalLayerType.INTEGRATION, "0", newDevice); - newDevice.addLayer(newlayer); - } - - //TODO: Use this to dynamically create enough layers to scroll through - //TODO: Use these to generate a rat's nest - for (const i in json.components) { - const newComponent = LoadUtils.loadComponentFromInterchangeV1(json.components[i]); - newDevice.addComponent(newComponent); - } - - for (const i in json.connections) { - const newConnection = LoadUtils.loadConnectionFromInterchangeV1(newDevice, json.connections[i]); - newDevice.addConnection(newConnection); - } - - if (Object.prototype.hasOwnProperty.call(json, "valves")) { - for (const i in json.valves) { - const newValve = json.valves[i]; - const component = newDevice.getComponentByID(newValve.componentid); - const connection = newDevice.getConnectionByID(newValve.connectionid); - if (component === null){ - console.warn("Could not find component with ID " + newValve.componentid + " for valve " + newValve.componentid); - throw new Error("Could not find component with ID " + newValve.componentid + " for valve " + newValve.componentid); - } - if (connection === null){ - console.warn("Could not find connection with ID " + newValve.connectionid + " for valve " + newValve.componentid); - throw new Error("Could not find connection with ID " + newValve.connectionid + " for valve " + newValve.componentid); - } - newDevice.insertValve(component, connection, newValve.type); - } - } else { - console.warn("Could not find valve map, using default valve map"); - } - - return newDevice; - } - - /** - * Loads the layer information from the interchange format - * - * @static - * @param {LayerInterchangeV1} jsonlayer - * @param {Device} device - * @returns {Layer} - * @memberof LoadUtils - */ - static loadLayerFromInterchangeV1(json: DeviceInterchangeV1, jsonlayer: LayerInterchangeV1, device: Device): Layer { - let layerType = LogicalLayerType.FLOW; - if (Object.prototype.hasOwnProperty.call(jsonlayer, "type")) { - if (jsonlayer.type === "FLOW") { - layerType = LogicalLayerType.FLOW; - } else if (jsonlayer.type === "CONTROL") { - layerType = LogicalLayerType.CONTROL; - } else if (jsonlayer.type === "INTEGRATION") { - layerType = LogicalLayerType.INTEGRATION; - } else { - throw new Error("Unknown layer type: " + jsonlayer.type); - } - } - const newLayer: Layer = new Layer(jsonlayer.params, jsonlayer.name, layerType, jsonlayer.group, device); - - if (jsonlayer.features) { - for (const i in jsonlayer.features) { - newLayer.features[jsonlayer.features[i].id] = LoadUtils.loadFeatureFromInterchangeV1(jsonlayer.features[i]); - } - newLayer.featureCount = jsonlayer.features.length; - } else { - //Generate features - - //Generate feature from components - const componentFeats: Array = LoadUtils.loadFeaturesFromComponentInterchangeV1(json, jsonlayer); - for (const k in componentFeats) { - newLayer.features[componentFeats[k].ID] = componentFeats[k]; - } - newLayer.featureCount = componentFeats.length; - - //Genereate feature from connection - const connectionFeats: Array = LoadUtils.loadFeaturesFromConnectionInterchangeV1(json, jsonlayer); - for (const k in connectionFeats) { - newLayer.features[connectionFeats[k].ID] = connectionFeats[k]; - } - newLayer.featureCount = newLayer.featureCount + connectionFeats.length; - } - newLayer.id = jsonlayer.id; - - return newLayer; - } - - /** - * Loads the features from the interchange format - * - * @static - * @param {FeatureInterchangeV1_2} json - * @returns {Feature} - * @memberof LoadUtils - */ - static loadFeatureFromInterchangeV1(json: FeatureInterchangeV1_2): Feature { - // TODO: This will have to change soon when the thing is updated - console.log("PARAMS: ", json.params); - let ret = Device.makeFeature(json.macro, json.params, json.name, json.id, json.type, json.dxfData); - if (Object.prototype.hasOwnProperty.call(json, "referenceID")) { - ret.referenceID = json.referenceID; - // Registry.currentDevice.updateObjectReference(json.id, json.referenceID); - } - return ret; - } - - /** - * Loads the features for layers with no feature category from component entries - * - * @static - * @param {DeviceInterchangeV1} json - * @param {LayerInterchangeV1} jsonlayer - * @returns {Array} - * @memberof LoadUtils - */ - static loadFeaturesFromComponentInterchangeV1(json: DeviceInterchangeV1, jsonlayer: LayerInterchangeV1): Array { - const ret: Array = []; - for (const i in json.components) { - const typestring = ComponentAPI.getTypeForMINT(json.components[i].entity); - if (typestring !== null) { - let feat: Feature; - const renderKeys: Array = ComponentAPI.getAllRenderKeys(typestring); - let group: string | null = null; - for (const j in json.layers) { - if (json.layers[j].id == json.components[i].layers[0]) group = json.layers[j].group; - } - if (group !== null) { - if (renderKeys.length == 1) { - if (json.components[i].layers[0] == jsonlayer.id) { - console.log("Assuming default type feature can be placed on current layer"); - const paramstoadd = json.components[i].params; - if (!Object.prototype.hasOwnProperty.call(json.components[i].params, "position")) { - paramstoadd.position = [0.0, 0.0]; - } - feat = Device.makeFeature(typestring, paramstoadd); - feat.referenceID = json.components[i].id; - ret.push(feat); - } - } else { - for (const j in renderKeys) { - if (renderKeys[j] == jsonlayer.type) { - if (group == jsonlayer.group) { - const paramstoadd = json.components[i].params; - if (!Object.prototype.hasOwnProperty.call(json.components[i].params, "position")) { - paramstoadd.position = [0.0, 0.0]; - } - if (ComponentAPI.library[typestring].key == jsonlayer.type) { - feat = Device.makeFeature(typestring, paramstoadd); - } else if (ComponentAPI.library[typestring + "_" + jsonlayer.type.toLowerCase()]) { - feat = Device.makeFeature(typestring + "_" + jsonlayer.type.toLowerCase(), paramstoadd); - } else { - console.log("Assuming default type feature can be placed on current layer"); - feat = Device.makeFeature(typestring, paramstoadd); - } - feat.referenceID = json.components[i].id; - ret.push(feat); - } - } - } - } - } - } else { - console.log("Mint " + json.components[i].entity + "not supported"); - } - } - return ret; - } - - /** - * Loads the features for layers with no feature category from connection entries - * - * @static - * @param {DeviceInterchangeV1} json - * @param {LayerInterchangeV1} jsonlayer - * @returns {Array} - * @memberof LoadUtils - */ - static loadFeaturesFromConnectionInterchangeV1(json: DeviceInterchangeV1, jsonlayer: LayerInterchangeV1): Array { - const ret: Array = []; - for (const i in json.connections) { - if (jsonlayer.id == json.connections[i].layer) { - const mint = json.connections[i].entity; - let typestring: string | null = null; - if (mint && mint != "CHANNEL") typestring = ComponentAPI.getTypeForMINT(json.connections[i].entity); - if (typestring === null) typestring = "Connection"; - - let feat: Feature; - let rawParams = json.connections[i].params; - if (rawParams.start) { - feat = Device.makeFeature(typestring, rawParams); - feat.referenceID = json.connections[i].id; - ret.push(feat); - } else { - if (json.connections[i].paths[0]) { - const wayPoints = json.connections[i].paths[0].wayPoints; - const segments: Array<[[number, number],[number,number]]> = []; - for (let k = 0; k < wayPoints.length - 1; k++) { - segments[k] = [wayPoints[k], wayPoints[k + 1]]; - } - const newParams = { - start: ["Point", wayPoints[0][0], wayPoints[0][1]], - end: wayPoints[wayPoints.length - 1], - wayPoints: wayPoints, - segments: segments, - connectionSpacing: rawParams.connectionSpacing, - channelWidth: rawParams.channelWidth, - height: ComponentAPI.getDefaultsForType(typestring).height - }; - feat = Device.makeFeature(typestring, newParams); - feat.referenceID = json.connections[i].id; - ret.push(feat); - } else { - console.log("Connection missing path description"); - } - } - } - } - return ret; - } - - /** - * Loads the features from component entries for layers missing from a group - * Assumes no connections present on undescribed layers - * Purpose is to fill in parts of components added later (e.g., integration layer part of picoinjector) - * @static - * @param {InterchangeV1_2} json - * @param {string} type - * @param {string} layerGroup - * @returns {Array} - * @memberof LoadUtils - */ - static generateMissingLayerFeaturesV1(json: InterchangeV1_2, type: string, layerGroup: string): Array { - const ret: Array = []; - for (const i in json.components) { - const typestring = ComponentAPI.getTypeForMINT(json.components[i].entity); - if (typestring !== null) { - if (type == "FLOW") { - const libEntry = ComponentAPI.library[typestring]; - if (libEntry != undefined && libEntry.key == "FLOW") { - let componentGroup: string | null = null; - for (const j in json.layers) { - if (json.layers[j].id == json.components[i].layers[0]) componentGroup = json.layers[j].group; - } - if (componentGroup !== null && componentGroup == layerGroup) { - const feat: Feature = Device.makeFeature(typestring, json.components[i].params); - feat.referenceID = json.components[i].id; - ret.push(feat); - } - } - } else { - if (ComponentAPI.library[typestring + "_" + type.toLowerCase()]) { - let componentGroup: string | null = null; - for (const j in json.layers) { - if (json.layers[j].id == json.components[i].layers[0]) componentGroup = json.layers[j].group; - } - if (componentGroup !== null && componentGroup == layerGroup) { - const feat: Feature = Device.makeFeature(typestring + "_" + type.toLowerCase(), json.components[i].params); - feat.referenceID = json.components[i].id; - ret.push(feat); - } - } - } - } else { - console.log("Mint " + json.components[i].entity + "not supported"); - } - } - return ret; - } - - /** - * Loads the connections from the interchange format - * - * @static - * @param {Device} device - * @param {ConnectionInterchangeV1_2} json - * @returns {Connection} - * @memberof LoadUtils - */ - static loadConnectionFromInterchangeV1(device: Device, json: ConnectionInterchangeV1_2): Connection { - const name = json.name; - const id = json.id; - const entity = json.entity; - let params = json.params; - const layer = device.getLayer(json.layer); - if (layer === null) { - throw new Error("Could not find layer with id: " + json.layer); - } - if (entity) { - // Check if the params have the other unique elements necessary otherwise add them as null - if (!Object.prototype.hasOwnProperty.call(params, "start")) { - if (json.paths[0]) { - params.start = ["Point", json.paths[0].wayPoints[0][0], json.paths[0].wayPoints[0][1]]; - } else { - // Setting this value to origin - params.start = [0, 0]; - } - } - if (!Object.prototype.hasOwnProperty.call(params, "end")) { - if (json.paths) { - params.end = json.paths[0].wayPoints[json.paths[0].wayPoints.length - 1]; - } else { - // Setting this value to origin - params.end = [0, 0]; - } - } - if (!Object.prototype.hasOwnProperty.call(params, "wayPoints")) { - // TODO: setting a single waypoint at origin - if (json.paths[0]) { - params.wayPoints = json.paths[0].wayPoints; - } else { - params.wayPoints = [ - [0, 0], - [1, 2] - ]; - } - } - if (!Object.prototype.hasOwnProperty.call(params, "segments")) { - // TODO: Setting a default segment from origin to origin - if (json.paths[0]) { - const segments: Array<[[number, number],[number,number]]> = []; - for (let k = 0; k < json.paths[0].wayPoints.length - 1; k++) { - segments[k] = [json.paths[0].wayPoints[k], json.paths[0].wayPoints[k + 1]]; - } - params.segments = segments; - } else { - params.segments = [ - [ - [0, 0], - [0, 0] - ], - [ - [0, 0], - [0, 0] - ] - ]; - } - } - if (!Object.prototype.hasOwnProperty.call(params, "height")) { - params.height = ComponentAPI.getDefaultsForType("Connection").height; - } - } else { - if (json.paths[0]) { - const wayPoints = json.paths[0].wayPoints; - const rawParams = json.params; - const segments: Array<[[number, number],[number,number]]> = []; - for (let k = 0; k < wayPoints.length - 1; k++) { - segments[k] = [wayPoints[k], wayPoints[k + 1]]; - } - const typestring = "Connection"; - params = { - start: ["Point", wayPoints[0][0], wayPoints[0][1]], - end: wayPoints[wayPoints.length - 1], - wayPoints: wayPoints, - segments: segments, - connectionSpacing: rawParams.connectionSpacing, - channelWidth: rawParams.channelWidth, - height: ComponentAPI.getDefaultsForType(typestring).height - }; - } else { - console.log("Connection missing path description"); - } - } - - let definition = ConnectionUtils.getDefinition("Connection"); - - if (definition === null || definition === undefined) { - throw new Error("Could not find the definition for the Connection"); - } - const paramstoadd = new Params(params, MapUtils.toMap(definition.unique), MapUtils.toMap(definition.heritable)); - const connection = new Connection(entity, paramstoadd, name, entity, layer, id); - if (Object.prototype.hasOwnProperty.call(json, "source")) { - if (json.source !== null && json.source !== undefined) { - connection.setSourceFromJSON(device, json.source); - } - } - if (Object.prototype.hasOwnProperty.call(json, "sinks")) { - if (json.sinks !== null && json.sinks !== undefined) { - for (const i in json.sinks) { - const sink = json.sinks[i]; - connection.addSinkFromJSON(device, sink); - } - } - } - if (Object.prototype.hasOwnProperty.call(json, "paths")) { - if (json.paths !== null && json.paths !== undefined) { - for (const i in json.paths) { - connection.addWayPoints(json.paths[i].wayPoints); - } - } - } - - return connection; - } - - /** - * Loads the components from the interchange format - * - * @static - * @param {ComponentInterchangeV1} json - * @returns {Component} - * @memberof LoadUtils - */ - static loadComponentFromInterchangeV1(json: ComponentInterchangeV1): Component { - const iscustomcompnent = false; - const name = json.name; - const id = json.id; - const entity = json.entity; - - // Idk whether this is correct - // It was originially this._span = this.span which threw several errors so I patterned in off the above const var - const xspan = json["x-span"]; - const yspan = json["y-span"]; - - const params = json.params; - - // TODO - remove this dependency - // iscustomcompnent = Registry.viewManager.customComponentManager.hasDefinition(entity); - - let definition; - - if (iscustomcompnent) { - definition = CustomComponent.defaultParameterDefinitions(); - } else { - definition = ComponentAPI.getDefinitionForMINT(entity); - } - - if (definition === null) { - //Is this the way to do this? - definition = ComponentAPI.getDefinition("Template"); - console.log("Def: ", definition); - } - - if (definition === null) { - throw Error("Could not find definition for type: " + entity); - } - - let type; - let value; - for (const key in json.params) { - if (Object.prototype.hasOwnProperty.call(definition.heritable, key)) { - type = definition.heritable[key]; - } else if (Object.prototype.hasOwnProperty.call(definition.unique, key)) { - type = definition.unique[key]; - } - // let paramobject = Parameter.generateComponentParameter(key, json.params[key]); - // Check if the value type is float and convert the value from string - value = json.params[key]; - if (type === "Float" && typeof value === "string") { - value = parseFloat(value); - } - - // let paramobject = new Parameter(type, value); - params[key] = value; - } - - // Do another check and see if position is present or not - if (!Object.prototype.hasOwnProperty.call(params, "position")) { - params.position = [0.0, 0.0]; - } - const unique_map = MapUtils.toMap(definition.unique); - const heritable_map = MapUtils.toMap(definition.heritable); - const paramstoadd = new Params(params, unique_map, heritable_map); - const component = new Component(paramstoadd, name, entity, id); - - // Deserialize the component ports - const portdata = new Map(); - for (const i in json.ports) { - const componentport = LoadUtils.loadComponentPortFromInterchangeV1(json.ports[i]); - portdata.set(componentport.label, componentport); - } - - component.ports = portdata; - - return component; - } - - /** - * Loads the component port from the interchange format - * - * @static - * @param {ComponentPortInterchangeV1} json - * @returns {ComponentPort} - * @memberof LoadUtils - */ - static loadComponentPortFromInterchangeV1(json: ComponentPortInterchangeV1): ComponentPort { - let layer_type = LogicalLayerType.FLOW; - if (json.layer === "FLOW"){ - layer_type = LogicalLayerType.FLOW; - } else if (json.layer === "CONTROL") { - layer_type = LogicalLayerType.CONTROL; - } else if (json.layer === "INTEGRATION") { - layer_type = LogicalLayerType.INTEGRATION; - } - return new ComponentPort(json.x, json.y, json.label, layer_type); - } - - /** - * Loads the renderlayers from the interchange format - * - * @static - * @param {RenderLayerInterchangeV1_2} json - * @param {Device} device - * @returns {RenderLayer} - * @memberof LoadUtils - */ - static loadRenderLayerFromInterchangeV1(json: RenderLayerInterchangeV1_2, device: Device): RenderLayer { - let layerType: LogicalLayerType | undefined; - if (Object.prototype.hasOwnProperty.call(json, "type")) { - if (json.type === "FLOW") { - layerType = LogicalLayerType.FLOW; - } else if (json.type === "CONTROL") { - layerType = LogicalLayerType.CONTROL; - } else if (json.type === "INTEGRATION") { - layerType = LogicalLayerType.INTEGRATION; - } else { - throw new Error("Unknown layer type: " + json.type); - } - } - const newLayer: RenderLayer = new RenderLayer(json.name, null, layerType); - - for (const i in json.features) { - newLayer.features[json.features[i].id] = LoadUtils.loadFeatureFromInterchangeV1(json.features[i]); - } - - if (json.modellayer) { - for (let i = 0; i < device.layers.length; i++) { - if (device.layers[i].id == json.modellayer) newLayer.physicalLayer = device.layers[i]; - } - } - if (json.color) newLayer.color = json.color; // TODO: Figure out if this needs to change in the future - return newLayer; - } - - /** - * Generates the render layers from the layer information. Typically used to generate all the render layers - * for the device. - * - * @static - * @param {LayerInterchangeV1} json - * @param {Device} device - * @returns {RenderLayer} - * @memberof LoadUtils - */ - static generateRenderLayerFromLayerInterchangeV1(json: LayerInterchangeV1, device: Device): RenderLayer { - let layerType: LogicalLayerType | undefined; - if (Object.prototype.hasOwnProperty.call(json, "type")) { - if (json.type === "FLOW") { - layerType = LogicalLayerType.FLOW; - } else if (json.type === "CONTROL") { - layerType = LogicalLayerType.CONTROL; - } else if (json.type === "INTEGRATION") { - layerType = LogicalLayerType.INTEGRATION; - } else { - throw new Error("Unknown layer type: " + json.type); - } - } - const newLayer: RenderLayer = new RenderLayer(json.name, null, layerType); - - for (const i in json.features) { - newLayer.features[json.features[i].id] = LoadUtils.loadFeatureFromInterchangeV1(json.features[i]); - } - - for (let i = 0; i < device.layers.length; i++) { - if (device.layers[i].id == json.id) newLayer.physicalLayer = device.layers[i]; - } - - if (Object.prototype.hasOwnProperty.call(json, "type")) { - if (json.type === "FLOW") { - newLayer.color = "indigo"; - } else if (json.type === "CONTROL") { - newLayer.color = "red"; - } else if (json.type === "INTEGRATION") { - newLayer.color = "green"; - } else { - throw new Error("Unknown layer type: " + json.type); - } - } - return newLayer; - } -} diff --git a/src/app/utils/mapUtils.ts b/src/app/utils/mapUtils.ts deleted file mode 100644 index 3d78254d..00000000 --- a/src/app/utils/mapUtils.ts +++ /dev/null @@ -1,11 +0,0 @@ -export default class MapUtils { - static toMap(obj: { [key: string]: any }): Map { - const map = new Map(); - for (const key in obj) { - if (Object.prototype.hasOwnProperty.call(obj, key)) { - map.set(key, obj[key]); - } - } - return map; - } -} diff --git a/src/app/utils/numberUtils.ts b/src/app/utils/numberUtils.ts deleted file mode 100644 index f8afc03b..00000000 --- a/src/app/utils/numberUtils.ts +++ /dev/null @@ -1,11 +0,0 @@ -export function isFloat(n: number): boolean { - return n === +n && n !== (n | 0); -} - -export function isInteger(n: number): boolean { - return n === +n && n === (n | 0); -} - -export function isFloatOrInt(n: number): boolean { - return isFloat(n) || isInteger(n); -} diff --git a/src/app/utils/paramUtils.nots b/src/app/utils/paramUtils.nots deleted file mode 100644 index b48a9506..00000000 --- a/src/app/utils/paramUtils.nots +++ /dev/null @@ -1,38 +0,0 @@ -import { Registry } from ".."; -import FloatValue from "@/app/core/parameters/floatValue"; -import { ComponentAPI } from "@/componentAPI"; - -export const generateUpdateFunction = function(sourceID, targetID, typeString, setString, paramString) { - return function() { - const source = document.getElementById(sourceID); - const target = document.getElementById(targetID); - let param; - if (!source?.value || source?.value === "") { - return; - } - try { - param = new FloatValue(parseFloat(source?.value)); - } catch (err) { - console.log("Invalid Float value."); - return; - } - target.value = String(param.getValue()); - Registry.viewManager?.adjustParams(typeString, setString, paramString, param.getValue()); - }; -}; - -export function revertToDefaultParams(typeString:string, setString:string) { - const def = ComponentAPI.getDefinition(typeString); - if (def === null){ - throw new Error("No definition found for " + typeString); - } - const heritable = def.heritable; - const defaults = def.defaults; - - for (const key in heritable) { - const type = heritable[key]; - - Registry.viewManager?.adjustParams(typeString, setString, key, defaults[key]); - - } -} diff --git a/src/app/utils/parchmintSanitizationUtils.ts b/src/app/utils/parchmintSanitizationUtils.ts deleted file mode 100644 index e59a484c..00000000 --- a/src/app/utils/parchmintSanitizationUtils.ts +++ /dev/null @@ -1,51 +0,0 @@ -export function sanitizeJSON(json: { [k: string]: any }): { [k: string]: any } { - const components = json.components; - - for (const component of components) { - const params = component.params; - - if (Object.prototype.hasOwnProperty.call(params, "orientation")) { - let rotation = 0; - const orientation = params.orientation; - if (orientation === "V") { - rotation = 0; - } else { - rotation = 270; - } - console.log(`Changed Param of Component '${component.name}' : ${orientation}->${rotation}`); - delete params.orientation; - params.rotation = rotation; - } - } - - const features_layers = json.features; - - for (const i in features_layers) { - const feature_layer = features_layers[i]; - const features = feature_layer.features; - console.log(features); - for (const j in features) { - const feature = features[j]; - - if (Object.prototype.hasOwnProperty.call(feature, "params")) { - const params = feature.params; - - if (Object.prototype.hasOwnProperty.call(params, "orientation")) { - let rotation = 0; - const orientation = params.orientation; - if (orientation === "V") { - rotation = 0; - } else { - rotation = 270; - } - console.log(`Changed Param of feature '${feature.name}' : ${orientation}->${rotation}`); - - delete params.orientation; - params.rotation = rotation; - } - } - } - } - - return json; -} diff --git a/src/app/utils/renderLayerUtils.ts b/src/app/utils/renderLayerUtils.ts deleted file mode 100644 index 49b1f9b3..00000000 --- a/src/app/utils/renderLayerUtils.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Registry } from ".."; -import Layer from "../core/layer"; -import RenderLayer from "../view/renderLayer"; - -/** - * Looks up the render layer for a given physical layer - * - * @export - * @param {Layer} physicalLayer - * @returns {(RenderLayer | null)} - */ -export function lookUpRenderLayer(physicalLayer: Layer): RenderLayer | null { - if (Registry.viewManager === null) { - throw new Error("View manager not set in registry"); - } - for (const layer of Registry.viewManager.renderLayers) { - if (layer.physicalLayer?.id === physicalLayer.id) { - return layer; - } - } - return null; -} \ No newline at end of file diff --git a/src/app/utils/renderUtils.ts b/src/app/utils/renderUtils.ts deleted file mode 100644 index 54dea88c..00000000 --- a/src/app/utils/renderUtils.ts +++ /dev/null @@ -1,81 +0,0 @@ -import Device from "../core/device"; -import Layer from "@/app/core/layer"; -import { LogicalLayerType } from "../core/init"; -import RenderLayer from "../view/renderLayer"; -import LoadUtils from "./loadUtils"; - -export function generateRenderLayers(device: Device): Array { - - let newRenderLayers: Array = []; - newRenderLayers.push(new RenderLayer(device.generateNewName("RenderLayerFlow"), device.layers[0], LogicalLayerType.FLOW)); - newRenderLayers.push(new RenderLayer(device.generateNewName("RenderLayerControl"), device.layers[1], LogicalLayerType.CONTROL)); - newRenderLayers.push(new RenderLayer(device.generateNewName("RenderLayerIntegration"), device.layers[0], LogicalLayerType.INTEGRATION)); - - // Ensures that there are three layers per group - let layerGroups: Map = new Map(); - for (let i = 0; i < device.layers.length; i++) { - if (layerGroups.has(device.layers[i].group)) { - const currentVal = layerGroups.get(device.layers[i].group); - if (currentVal) layerGroups.set(device.layers[i].group, currentVal + 1); - } else { - layerGroups.set(device.layers[i].group, 1); - } - } - - // layerGroups.forEach((value, key) => { - // const keyVal = parseInt(key, 10); - - // if (value == 3) { - // console.log("All layers accounted for in group " + key); - // } else { - // const layerTypes: Array = ["FLOW", "CONTROL", "INTEGRATION"]; - // for (const i in json.layers) { - // const index = layerTypes.indexOf(json.layers[i].type); - // layerTypes.splice(index, 1); - // } - // console.log(layerTypes.length + " layers missing from group " + key + ", these will be generated"); - // for (const j in layerTypes) { - // const featuresToAdd = LoadUtils.generateMissingLayerFeaturesV1(json, layerTypes[j], key); - // if (layerTypes[j] == "FLOW") { - // const newLayer = new Layer({}, device.generateNewName("LayerFlow"), LogicalLayerType.FLOW, key, device); - // for (const k in featuresToAdd) { - // newLayer.features[featuresToAdd[k].ID] = featuresToAdd[k]; - // } - // newLayer.featureCount = featuresToAdd.length; - // device.addLayerAtIndex(newLayer, keyVal * 3); - // newRenderLayers.splice(keyVal * 3, 0, new RenderLayer(device.generateNewName("RenderLayerFlow"), device.layers[keyVal * 3], LogicalLayerType.FLOW)); - // } - // else if (layerTypes[j] == "CONTROL") { - // const newLayer = new Layer({}, device.generateNewName("LayerControl"), LogicalLayerType.CONTROL, key, device); - // for (const k in featuresToAdd) { - // newLayer.features[featuresToAdd[k].ID] = featuresToAdd[k]; - // } - // newLayer.featureCount = featuresToAdd.length; - // device.addLayerAtIndex(newLayer, keyVal * 3 + 1); - // newRenderLayers.splice(keyVal * 3 + 1, 0, new RenderLayer(device.generateNewName("RenderLayerControl"), device.layers[keyVal * 3 + 1], LogicalLayerType.CONTROL)); - // } - // else if (layerTypes[j] == "INTEGRATION") { - // const newLayer = new Layer({}, device.generateNewName("LayerIntegration"), LogicalLayerType.INTEGRATION, key, device); - // for (const k in featuresToAdd) { - // newLayer.features[featuresToAdd[k].ID] = featuresToAdd[k]; - // } - // newLayer.featureCount = featuresToAdd.length; - // device.addLayerAtIndex(newLayer, keyVal * 3 + 2); - // newRenderLayers.splice(keyVal * 3 + 2, 0, new RenderLayer(device.generateNewName("RenderLayerIntegration"), device.layers[keyVal * 3 + 2], LogicalLayerType.INTEGRATION)); - // } - // } - // } - // }); - - // //Updating cross-references - // let features = device.getAllFeaturesFromDevice(); - // for (let i in features) { - // const feature = features[i]; - // if (feature.referenceID !== null) { - // device.updateObjectReference(feature.referenceID, feature.ID); - // } - // } - - return newRenderLayers; - -} \ No newline at end of file diff --git a/src/app/utils/simpleQueue.ts b/src/app/utils/simpleQueue.ts deleted file mode 100644 index f8b3211f..00000000 --- a/src/app/utils/simpleQueue.ts +++ /dev/null @@ -1,47 +0,0 @@ -export default class SimpleQueue { - timeout?: number; - func: () => any; - waiting: boolean; - queued: boolean; - counter: number; - report: boolean; - - constructor(func: () => any, timeout?: number, report = false) { - this.timeout = timeout; - this.func = func; - this.waiting = false; - this.queued = true; - this.counter = 0; - this.report = report; - } - - run(): void { - if (this.waiting) { - this.counter++; - if (!this.queued) { - this.queued = true; - } - } else { - if (this.report) console.log("Waited " + this.counter + " times."); - this.func(); - this.startTimer(); - this.counter = 0; - } - } - - endTimer(): void { - this.waiting = false; - if (this.queued) { - this.queued = false; - this.run(); - } - } - - startTimer(): void { - const ref = this; - this.waiting = true; - window.setTimeout(function() { - ref.endTimer(); - }, this.timeout); - } -} diff --git a/src/app/utils/stringUtils.ts b/src/app/utils/stringUtils.ts deleted file mode 100644 index f8e3749f..00000000 --- a/src/app/utils/stringUtils.ts +++ /dev/null @@ -1,4 +0,0 @@ -// from http://stackoverflow.com/questions/1026069/capitalize-the-first-letter-of-string-in-javascript -export function capitalizeFirstLetter(string: string): string { - return string.charAt(0).toUpperCase() + string.slice(1); -} diff --git a/src/app/view/colors.ts b/src/app/view/colors.ts deleted file mode 100644 index 291174ee..00000000 --- a/src/app/view/colors.ts +++ /dev/null @@ -1,195 +0,0 @@ -// import Feature from "../core/feature"; -import * as paper from "paper"; -import Layer from "../core/layer"; -import { LogicalLayerType } from "@/app/core/init"; -import RenderLayer from "./renderLayer"; - -// Colors taken from: http://www.google.ch/design/spec/style/color.html -export const RED_500 = "#F44336"; -export const INDIGO_500 = "#3F51B5"; -export const GREEN_500 = "#4CAF50"; -export const GREEN_100 = "#C8E6C9"; -export const GREEN_A200 = "#69F0AE"; -export const DEEP_PURPLE_500 = "#673AB7"; -export const PURPLE_200 = "#E1BEE7"; -export const PURPLE_100 = "#E1BEE7"; -export const TEAL_100 = "#B2DFDB"; -export const BLUE_50 = "#e3f2fd"; -export const BLUE_100 = "#BBDEFB"; -export const BLUE_200 = "#90CAF9"; -export const BLUE_300 = "#64B5F6"; -export const BLUE_500 = "#2196F3"; -export const GREY_200 = "#EEEEEE"; -export const GREY_300 = "#E0E0E0"; -export const GREY_400 = "#BDBDBD"; -export const LIGHT_GREEN_100 = "#DCEDC8"; -export const GREY_700 = "#616161"; -export const GREY_500 = "#9E9E9E"; -export const AMBER_50 = "#FFF8E1"; -export const PINK_500 = "#E91E63"; -export const PINK_300 = "#F06292"; -export const BLACK = "#000000"; -export const WHITE = "#FFFFFF"; - -export const defaultColorKeys = ["50", "100", "200", "300", "400", "500", "600", "700", "800", "900"]; -export const darkColorKeys = ["300", "400", "500", "600", "700", "800", "900"]; - -const indigo = { - 900: "#" + "1A237E", - 800: "#" + "283593", - 700: "#" + "303F9F", - 600: "#" + "3949AB", - 500: "#" + "3F51B5", - 400: "#" + "5C6BC0", - 300: "#" + "7986CB", - 200: "#" + "9FA8DA", - 100: "#" + "C5CAE9", - 50: "#" + "E8EAF6", - A100: "#" + "8C9EFF", - A200: "#" + "536DFE", - A400: "#" + "3D5AFE", - A700: "#" + "304FFE" -}; - -const red = { - 900: "#" + "B71C1C", - 800: "#" + "C62828", - 700: "#" + "D32F2F", - 600: "#" + "E53935", - 500: "#" + "F44336", - 400: "#" + "EF5350", - 300: "#" + "E57373", - 200: "#" + "EF9A9A", - 100: "#" + "FFCDD2", - 50: "#" + "FFEBEE", - A100: "#" + "FF8A80", - A200: "#" + "FF5252", - A400: "#" + "FF1744", - A700: "#" + "D50000" -}; - -const blue = { - 900: "#" + "1A237E", - 800: "#" + "283593", - 700: "#" + "303F9F", - 600: "#" + "3949AB", - 500: "#" + "3F51B5", - 400: "#" + "5C6BC0", - 300: "#" + "7986CB", - 200: "#" + "9FA8DA", - 100: "#" + "C5CAE9", - 50: "#" + "E8EAF6", - A100: "#" + "8C9EFF", - A200: "#" + "536DFE", - A400: "#" + "3D5AFE", - A700: "#" + "304FFE" -}; - -const green = { - 900: "#" + "006200", - 800: "#" + "007600", - 700: "#" + "008900", - 600: "#" + "009d00", - 500: "#" + "00b100", - 400: "#" + "00d800", - 300: "#" + "00ff00", - 200: "#" + "3bff3b", - 100: "#" + "62ff62", - 50: "#" + "b1ffb1", - A100: "#" + "ebffeb", - A200: "#" + "9dff9d", - A400: "#" + "14ff14", - A700: "#" + "00b100" -}; - -const layerColors = { - indigo: indigo, - red: red, - blue: blue, - green: green -}; -/** - * Converts from decimal to index - * @param {number} decimal - * @param {number} indices - * @returns {number} - */ -const decimalToIndex = function(decimal: number, indices: number) { - return Math.round((indices - 1) * decimal); -}; -/** - * Converts the decimal to the corresponding layer color - * @param {number} decimal - * @param {Object} layerColors - * @param {Array} orderedKeys - */ -export function decimalToLayerColor(decimal: number, layerColors: { [k: string]: string }, orderedKeys: string[]): string { - const index = decimalToIndex(decimal, orderedKeys.length); - const key = orderedKeys[index]; - return layerColors["700"]; -} -/** - * Renders all the colors - * @param {Layer} layer - * @param {Array} orderedKeys - */ -export function renderAllColors(layer: { [k: string]: string }, orderedKeys: string[]): void { - for (let i = 0; i < orderedKeys.length; i++) { - new paper.Path.Circle({ - position: new paper.Point(0 + i * 1000, 0), - fillColor: layer[orderedKeys[i]], - radius: 500 - }); - } - - for (let i = 0; i < orderedKeys.length; i++) { - const color = decimalToLayerColor(i / orderedKeys.length, layer, orderedKeys); - new paper.Path.Circle({ - position: new paper.Point(0 + i * 1000, 2000), - fillColor: layer[orderedKeys[i]], - radius: 500 - }); - } -} -/** - * Gets the color corresponding to the layer. - * @param {Layer} layerType - */ -export function getLayerColors(layerType: LogicalLayerType) { - if (!layerType) { - throw new Error("Undefined color"); - } - - if (layerType == LogicalLayerType.FLOW) { - return layerColors.indigo; - } else if (layerType == LogicalLayerType.CONTROL) { - return layerColors.red; - } else if (layerType == LogicalLayerType.INTEGRATION) { - return layerColors.green; - } else { - throw new Error("Undefined LogicalLayerType"); - } -} -/** - * Gets the default color for the layer - * @param {Layer} layer - */ -export function getDefaultLayerColor(layer: Layer) { - if (layer === undefined) { - throw new Error("Undefined layer object passed"); - } - return getLayerColors(layer.type)["500"]; -} - -// TODO: We need to fix how this works and remove the circular dependency form this chain -export function getDefaultFeatureColor(typeString: string, layer: RenderLayer) { - if (layer) { - // let height = Feature.getDefaultsForType(typeString, setString)["height"]; - let decimal = 500; // layer.estimateLayerHeight(); - // if (!(layer as any).flip) decimal = 1 - decimal; - const colors = getLayerColors(layer.type); - return decimalToLayerColor(decimal, colors, darkColorKeys); - } else { - return decimalToLayerColor(0, layerColors.indigo, darkColorKeys); - } -} diff --git a/src/app/view/customComponentManager.ts b/src/app/view/customComponentManager.ts deleted file mode 100644 index 837185e0..00000000 --- a/src/app/view/customComponentManager.ts +++ /dev/null @@ -1,116 +0,0 @@ -import CustomComponent from "../core/customComponent"; -import Registry from "../core/registry"; -import ViewManager from "./viewManager"; - -export default class CustomComponentManager { - viewManagerDelegate: ViewManager; - private __library: Map; - - /** - * Default Constructor of the CustomComponentManger object - * @param {*} viewManager - */ - constructor(viewManager: ViewManager) { - this.viewManagerDelegate = viewManager; - this.__library = new Map(); - - // set up registry for custom tools - } - - /** - * Gets the library - * @memberof CustomComponentManager - * @returns {} - */ - get library() { - return this.__library; - } - - /** - * Inserts a new component - * @param {string} type Type of component - * @param dxfdata DXF data - * @param renderData Render data - * @returns {void} - * @memberof CustomComponentManager - */ - importComponentFromDXF(type: string, dxfdata: any, renderData: any): void { - // console.log("Yay ! loaded the data", dxfdata); - // console.log("Render Data", renderData); - // Create DXF Objects - const customcomponent = new CustomComponent(type, dxfdata); - customcomponent.renderData = renderData; - this.__library.set(type, customcomponent); - this.viewManagerDelegate.addCustomComponentTool(type); - // TODO: Update the Vue UI via the component API - // (this.viewManagerDelegate as any).rightPanel.customComponentToolBar.updateToolBar(); - } - - /** - * Import a new component from a JSON format - * @param {CustomComponent} customcomponent Custom component object - * @returns {void} - * @memberof CustomComponentManager - */ - __importComponentFromDeserializedJSON(customcomponent: CustomComponent): void { - this.__library.set(customcomponent.type, customcomponent); - this.viewManagerDelegate.addCustomComponentTool(customcomponent.type); - // TODO - Update the Vue UI via the component API - // (this.viewManagerDelegate as any).rightPanel.customComponentToolBar.updateToolBar(); - } - - /** - * Gets the custom component - * @param {*} componenttype - * @returns {} - * @memberof CustomComponentManager - */ - getCustomComponent(componenttype: string) { - return this.__library.get(componenttype); - } - - /** - * Converts to JSON format - * @returns {JSON} - * @memberof CustomComponentManager - */ - toJSON() { - const ret: { [k: string]: any } = {}; - - for (const key of this.__library.keys()) { - const customcomponent = this.__library.get(key); - // console.log("Key:", key); - // console.log("Key:", customcomponent); - ret[key] = customcomponent.toJSON(); - } - - // console.log("library", this.__library); - // console.log("ret", ret); - - return ret; - } - - /** - * Loads from a JSON format - * @param {JSON} json - * @memberof CustomComponentManager - * @returns {void} - */ - loadFromJSON(json: { [k: string]: any }): void { - for (const key in json) { - const customcomponent = CustomComponent.fromInterchangeV1(json[key]); - - this.__importComponentFromDeserializedJSON(customcomponent); - } - } - - /** - * Checks if the library has a definition ? - * @param {*} entity - * @returns {} - * @memberof CustomComponentManager - */ - hasDefinition(entity: any): boolean { - return this.__library.has(entity); - } -} diff --git a/src/app/view/designHistory.ts b/src/app/view/designHistory.ts deleted file mode 100644 index 158fdc96..00000000 --- a/src/app/view/designHistory.ts +++ /dev/null @@ -1,74 +0,0 @@ -import md5 from "md5"; -import Device from "../core/device"; - -const HISTORY_SIZE = 50; -/** - * Design History class - */ -export default class DesignHistory { - deviceData: any[]; - private __mostRecentMD5: string | null; - - /** - * Default Construcot for the Design History object - */ - constructor() { - this.deviceData = []; - this.__mostRecentMD5 = null; - } - - /** - * Adds new design to the design history - * @param {Array} devicedata - * @returns {void} - * @memberof DesignHistory - */ - pushDesign(devicedata: string): void { - // Calculate md5 hash and see if we want so save this design - const hash = md5(devicedata); - if (this.__mostRecentMD5) { - if (hash === this.__mostRecentMD5) { - return; - } - } - // Remove data from the undo stack if there is too much info there - if (this.deviceData.length > HISTORY_SIZE) { - this.deviceData.splice(0, 1); - } - - // Add to design - this.deviceData.push(devicedata); - this.__mostRecentMD5 = hash; - console.log("Saved new state:", hash); - } - - /** - * Removes a design from the history - * @returns {Device} - * @memberof DesignHistory - */ - popDesign(): string | null { - if (this.deviceData.length > 0) { - const device = this.deviceData.pop(); - return device; - } else { - return null; - } - } - - /** - * Deep copys the object being stored in the design - * @param obj - * @returns {Object} - * @memberof DesignHistory - * @private - */ - __cloneObject(obj: { [k: string]: any }) { - const clone: { [k: string]: any } = {}; - for (const i in obj) { - if (obj[i] !== null && typeof obj[i] === "object") clone[i] = this.__cloneObject(obj[i]); - else clone[i] = obj[i]; - } - return clone; - } -} diff --git a/src/app/view/grid/adaptiveGrid.ts b/src/app/view/grid/adaptiveGrid.ts deleted file mode 100644 index 829f49f2..00000000 --- a/src/app/view/grid/adaptiveGrid.ts +++ /dev/null @@ -1,151 +0,0 @@ -import { ViewManager } from "@/app"; -import paper from "paper"; - -import * as Colors from "../colors"; - -export default class AdaptiveGrid { - private __viewManagerDelegate: ViewManager; - private __spacing: number; - private __isAutomaticEnabled: boolean; - - origin: paper.Point; - thinWidth: number; - thickWidth: number; - minSpacing: number; - maxSpacing: number; - thickCount: number; - color: paper.Color; - - constructor(viewmanager: ViewManager, minSpacing = 5, maxSpacing = 100, thickCount = 10, origin = [0, 0], thinWidth = 1, thickWidth = 3, color = Colors.BLUE_100) { - this.__viewManagerDelegate = viewmanager; - - this.origin = new paper.Point(origin[0], origin[1]); - this.thinWidth = thinWidth; // pixel - this.thickWidth = thickWidth; // pixels - this.minSpacing = minSpacing; // pixels - this.maxSpacing = maxSpacing; // pixels - this.thickCount = thickCount; - this.__spacing = 500; - this.__isAutomaticEnabled = true; - this.color = new paper.Color(color); - } - - /** - * Returns the current grid spacing - * - * @type {number} - * @memberof AdaptiveGrid - */ - get spacing(): number { - return this.__spacing; - } - - set spacing(value) { - // You can have validation code here - console.log(AdaptiveGrid.isValidZoom(value)); - this.__spacing = value; - } - - enableAdaptiveGrid(): void { - this.__isAutomaticEnabled = true; - } - - disableAdaptiveGrid(): void { - this.__isAutomaticEnabled = false; - } - - getClosestGridPoint(point: paper.Point) { - const x = Math.round((point.x - this.origin.x) / this.__spacing) * this.__spacing + this.origin.x; - const y = Math.round((point.y - this.origin.y) / this.__spacing) * this.__spacing + this.origin.y; - return new paper.Point(x, y); - } - - setOrigin(origin: number[]): void { - this.origin = new paper.Point(origin[0], origin[1]); - this.notifyViewManagerToUpdateView(); - } - - setThinWidth(width: number): void { - this.thinWidth = width; - this.notifyViewManagerToUpdateView(); - } - - setThickWidth(width: number): void { - this.thickWidth = width; - this.notifyViewManagerToUpdateView(); - } - - setMinSpacing(pixels: number): void { - this.__spacing = pixels; - this.notifyViewManagerToUpdateView(); - } - - setMaxSpacing(pixels: number): void { - this.maxSpacing = pixels; - this.notifyViewManagerToUpdateView(); - } - - setColor(color: string): void { - this.color = new paper.Color(color); - this.notifyViewManagerToUpdateView(); - } - - getSpacing(): number { - if (this.__isAutomaticEnabled) { - const zoomlevel = paper.view.zoom; - if (zoomlevel <= 0.02) { - this.__spacing = 1000; - } else if (zoomlevel <= 0.05) { - this.__spacing = 500; - } else if (zoomlevel <= 0.1) { - this.__spacing = 100; - } else if (zoomlevel <= 0.6) { - this.__spacing = 50; - } else { - this.__spacing = 5; - } - return this.__spacing; - } else { - return this.__spacing; - } - // console.log("Zoom: " + paper.view.zoom + " Spacing: " + this.__spacing); - } - - updateGridSpacing(value: number): boolean { - if (AdaptiveGrid.isValidZoom(value)) { - console.log("New spacing value:", value); - this.__spacing = value; - return true; - } else { - console.error("Inavlid Grid Spacing"); - return false; - } - } - - getThinWidth(): number { - return this.thinWidth / paper.view.zoom; - } - - getThickWidth(): number { - return this.thickWidth / paper.view.zoom; - } - - notifyViewManagerToUpdateView(): void { - if (this.__viewManagerDelegate) { - this.__viewManagerDelegate.updateGrid(); - } else { - console.error("Could not find view manager to send update grid signal"); - } - } - - static isValidZoom(value: number): boolean { - // First check if its a valid number - - // TODO: figure out if we want to round it off - - // Then check if its in bounds - - // TODO: change this to be actually functional - return true; - } -} diff --git a/src/app/view/mouseAndKeyboardHandler.ts b/src/app/view/mouseAndKeyboardHandler.ts deleted file mode 100644 index 2ea0ce05..00000000 --- a/src/app/view/mouseAndKeyboardHandler.ts +++ /dev/null @@ -1,325 +0,0 @@ -import paper from "paper"; -import PanTool from "./tools/panTool"; -import EventBus from "@/events/events"; -import { ViewManager } from ".."; - -/** - * Mouse and Keyboard Handler class - */ -export default class MouseAndKeyboardHandler { - viewManagerDelegate: ViewManager; - - private __leftMouseTool: any; - private __rightMouseTool: any; - private __middleMouseTool: any; - - /** - * Default Constructor for MouseAndKeyboardHandler object - * @param {*} viewManagerDelegate - */ - constructor(viewManagerDelegate: ViewManager) { - this.viewManagerDelegate = viewManagerDelegate; - - this.__leftMouseTool = null; - this.__rightMouseTool = null; - this.__middleMouseTool = new PanTool(viewManagerDelegate); - - // Prevent default keyboard window events - window.onkeydown = function(event: KeyboardEvent) { - const key = event.keyCode || event.which; - if (key === 46) { - event.preventDefault(); - } - }; - - this.__setupDefaultKeyboardShortcuts(); - // this.__updateViewMouseEvents(); - } - - /** - * Sets the tool for the left mouse - * @returns {void} - * @memberof MouseAndKeyboardHandler - */ - set leftMouseTool(tool) { - this.__leftMouseTool = tool; - } - - /** - * Sets the tool for the right mouse - * @param {} tool Selected tool - * @returns {void} - * @memberof MouseAndKeyboardHandler - */ - set rightMouseTool(tool) { - this.__rightMouseTool = tool; - } - - /** - * Gets the tool of the left mouse - * @returns Returns left mouse tool - * @memberof MouseAndKeyboardHandler - */ - get leftMouseTool() { - return this.__leftMouseTool; - } - - /** - * Gets the tool of the right mouse - * @returns Returns right mouse tool - * @memberof MouseAndKeyboardHandler - */ - get rightMouseTool() { - return this.__rightMouseTool; - } - - /** - * Sets up the default keyboard handlers - * @returns {void} - * @memberof MouseAndKeyboardHandler - * @private - */ - private __setupDefaultKeyboardShortcuts() { - const reference = this.viewManagerDelegate; - - window.addEventListener("keydown", function(event) { - const key = event.keyCode || event.which; - - // Saving - if ((event.ctrlKey || event.metaKey) && key === 83) { - event.preventDefault(); - reference.downloadJSON(); - } - - if (key === 70) { - // Reset the view - reference.view.initializeView(); - reference.updateGrid(); - reference.view.updateAlignmentMarks(); - event.preventDefault(); - } - - // Escape key - if (key === 27) { - // Deselect all - paper.project.deselectAll(); - - // Change active tool to select tool - reference.resetToDefaultTool(); - - // Close all windows/dialogs - EventBus.get().emit(EventBus.CLOSE_ALL_WINDOWS); - } - }); - - reference.view.setKeyDownFunction(function(event) { - const key = event.keyCode || event.which; - - // Delete - if (key === 46 || key === 8) { - reference.saveDeviceState(); - reference.view.deleteSelectedFeatures(); - } - // Copy - if ((event.ctrlKey || event.metaKey) && key === 67) { - // console.log("Ctl c detected"); - reference.initiateCopy(); - } - // Cut - if ((event.ctrlKey || event.metaKey) && key === 88) { - // console.log("Ctl x detected"); - const selectedFeatures = reference.view.getSelectedFeatures(); - if (selectedFeatures.length > 0) { - reference.pasteboard[0] = selectedFeatures[0]; - } - reference.saveDeviceState(); - reference.view.deleteSelectedFeatures(); - } - // Paste - if ((event.ctrlKey || event.metaKey) && key === 86) { - // console.log("Ctl v detected"); - const pasteboardFeatures = reference.pasteboard; - if (pasteboardFeatures.length > 0) { - reference.updateDefaultsFromFeature(pasteboardFeatures[0]); - reference.activateTool(pasteboardFeatures[0].getType()); - } - } - - // Undo - if (event.keyCode === 90 && (event.metaKey || event.ctrlKey)) { - console.log("Undo executed"); - reference.undo(); - } - - let pan_multiplier; - - if (key === 37) { - // console.log("left arrow"); - if (event.shiftKey) { - pan_multiplier = 10; - } else if (event.ctrlKey) { - pan_multiplier = 0.1; - } else { - pan_multiplier = 1; - } - reference.view.moveCenter(new paper.Point(1000 * pan_multiplier, 0)); - reference.updateGrid(); - reference.view.updateAlignmentMarks(); - } - - if (key === 38) { - // console.log("Up arrow"); - if (event.shiftKey) { - pan_multiplier = 10; - } else if (event.ctrlKey) { - pan_multiplier = 0.1; - } else { - pan_multiplier = 1; - } - reference.view.moveCenter(new paper.Point(0, 1000 * pan_multiplier)); - reference.updateGrid(); - reference.view.updateAlignmentMarks(); - } - - if (key === 39) { - // console.log("right arrow"); - if (event.shiftKey) { - pan_multiplier = 10; - } else if (event.ctrlKey) { - pan_multiplier = 0.1; - } else { - pan_multiplier = 1; - } - reference.view.moveCenter((new paper.Point(-1000 * pan_multiplier, 0))); - reference.updateGrid(); - reference.view.updateAlignmentMarks(); - } - - if (key === 40) { - // console.log("down arrow"); - if (event.shiftKey) { - pan_multiplier = 10; - } else if (event.ctrlKey) { - pan_multiplier = 0.1; - } else { - pan_multiplier = 1; - } - reference.view.moveCenter(new paper.Point(0, -1000 * pan_multiplier)); - reference.updateGrid(); - reference.view.updateAlignmentMarks(); - } - - if ((event.ctrlKey || event.metaKey) && key === 65) { - // Select all - reference.view.selectAllActive(); - return false; - } - }); - } - - /** - * Updates mouse events - * @returns {void} - * @memberof MouseAndKeyboardHandler - */ - updateViewMouseEvents(): void { - this.viewManagerDelegate.view.setMouseDownFunction(this.constructMouseDownEvent(this.__leftMouseTool, this.__middleMouseTool, this.__leftMouseTool)); - this.viewManagerDelegate.view.setMouseUpFunction(this.constructMouseUpEvent(this.__leftMouseTool, this.__middleMouseTool, this.__leftMouseTool)); - this.viewManagerDelegate.view.setMouseMoveFunction(this.constructMouseMoveEvent(this.__leftMouseTool, this.__middleMouseTool, this.__leftMouseTool)); - } - - /** - * This function is executed as a callback for every mouse down event - * @memberof MouseAndKeyboardHandler - * @returns {void} - * @private - */ - private __mouseDownCallback(event: any) { - console.log("testing down callback", event); - } - - /** - * this function is executed as a callback for every mouse up event - * @memberof MouseAndKeyboardHandler - * @returns {void} - * @private - */ - private __mouseUpCallback(event: any) { - console.log("testing up callback", event); - } - - /** - * This function is executed as a callback for every mouse move event - * @memberof MouseAndKeyboardHandler - * @returns {void} - * @private - */ - private __mouseMoveCallback(event: any) { - console.log("testing move callback", event); - } - - /** - * - * @param {*} tool1 - * @param {*} tool2 - * @param {*} tool3 - */ - constructMouseDownEvent(tool1: any, tool2: any, tool3: any) { - console.log("Tool1: ", tool1, "Tool2: ", tool2, "Tool3: ", tool3); - if (tool1 === tool3) { - console.log("Both right and left tool is the same"); - return this.constructMouseEvent(tool1.down, tool2.down, tool3.rightdown, this.__mouseDownCallback); - } else { - return this.constructMouseEvent(tool1.down, tool2.down, tool3.down); - } - } - - constructMouseMoveEvent(tool1: any, tool2: any, tool3: any) { - return this.constructMouseEvent(tool1.move, tool2.move, tool3.move, this.__mouseUpCallback); - } - - constructMouseUpEvent(tool1: any, tool2: any, tool3: any) { - return this.constructMouseEvent(tool1.up, tool2.up, tool3.up, this.__mouseMoveCallback); - } - - /** - * - * @param {*} func1 - * @param {*} func2 - * @param {*} func3 - * @param {*} buttondownCallback - * @memberof MouseAndKeyboardHandler - * @returns {Function} - */ - constructMouseEvent(func1: (...args: any[]) => any, func2: (...args: any[]) => any, func3: (...args: any[]) => any, buttondownCallback?: (...args: any[]) => any) { - console.log("construct mouse event!"); - return function(event: any) { - let target; - if (event.buttons) { - buttondownCallback!(event); - target = MouseAndKeyboardHandler.__eventButtonsToWhich(event.buttons); - } else { - target = event.which; - } - if (target === 2) { - func2(event); - } else if (target === 3) { - func3(event); - } else if (target === 1 || target === 0) { - func1(event); - } - }; - } - - static __eventButtonsToWhich(num: number): number | undefined { - if (num === 1) { - return 1; - } else if (num === 2) { - return 3; - } else if (num === 4) { - return 2; - } else if (num === 3) { - return 2; - } - } -} diff --git a/src/app/view/panAndZoom.ts b/src/app/view/panAndZoom.ts deleted file mode 100644 index 6c8c9a32..00000000 --- a/src/app/view/panAndZoom.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { PaperView } from ".."; - -/** - * Pan and Zoom class - */ -export default class PanAndZoom { - view: PaperView; - - /** - * Default Constructor for the PanAndZoom object - * @param {*} paperView - */ - constructor(paperView: PaperView) { - this.view = paperView; - } - - /** - * Sets a zoom value to a certain position - * @param {number} zoom Zoom value - * @param {Array} position X and Y coordinates - * @returns {void} - * @memberof PanAndZoom - */ - stableZoom(zoom: number, position: paper.Point): void { - const newZoom = zoom; - const p = position; - const c = this.view.getCenter(); - const beta = this.view.getZoom() / newZoom; - const pc = p.subtract(c); - const a = p.subtract(pc.multiply(beta)).subtract(c); - this.view.setCenter(this.view.getCenter().add(a)); - this.view.setZoom(newZoom); - } - - /** - * Adjust the zoom and the position - * @param {number} delta Value of adjustment of the zoom value - * @param {Array} position X and Y coordinates - * @returns {void} - * @memberof PanAndZoom - */ - adjustZoom(delta: number, position: paper.Point): void { - this.stableZoom(this.calcZoom(delta), position); - } - - // Stable pan and zoom modified from: http://matthiasberth.com/articles/stable-zoom-and-pan-in-paperjs/ - /** - * Calculates the zoom - * @param {number} delta Value of adjustment of the zoom value - * @param {number} multiplier Default = 1.177827941003 - * @returns {number} - * @memberof PanAndZoom - */ - calcZoom(delta: number, multiplier = 1.177827941003): number { - if (delta < 0) return this.view.getZoom() * multiplier; - else if (delta > 0) return this.view.getZoom() / multiplier; - else return this.view.getZoom(); - } - - /** - * Updates the center coordinates - * @param {number} delta Value of adjustment of the zoom value - * @returns {void} - * @memberof PanAndZoom - */ - moveCenter(delta: paper.Point): void { - this.view.setCenter(this.calcCenter(delta)); - } - - /** - * Calculates the new center position - * @param {number} delta Value of adjustment of the zoom value - * @returns {Array} Returns and array with X and Y coordinates - * @memberof PanAndZoom - */ - calcCenter(delta: paper.Point): paper.Point { - return this.view.getCenter().subtract(delta); - } -} diff --git a/src/app/view/paperView.ts b/src/app/view/paperView.ts deleted file mode 100644 index 37ca54ff..00000000 --- a/src/app/view/paperView.ts +++ /dev/null @@ -1,1292 +0,0 @@ -import uuid from "node-uuid"; -import EdgeFeature from "../core/edgeFeature"; -import paper from "paper"; -import { ComponentAPI } from "@/componentAPI"; - -import Registry from "../core/registry"; -import * as FeatureRenderer2D from "./render2D/featureRenderer2D"; -import GridRenderer from "./render2D/gridRenderer"; -import DeviceRenderer from "./render2D/deviceRenderer2D"; -// const DeviceRenderer = require("./render2D/deviceRenderer2D"); -// var AlignmentRenderer = require("./render2D/alignmentRenderer2D"); -import PanAndZoom from "./panAndZoom"; -import * as Colors from "./colors"; -import ManufacturingLayer from "../manufacturing/manufacturingLayer"; -import RatsNestRenderer2D from "./render2D/ratsNestRenderer2D"; -import ComponentPortRenderer2D from "./render2D/componentPortRenderer2D"; -import PaperComponentPortView from "./render2D/paperComponentPortView"; -import * as DXFObjectRenderer2D from "./render2D/dxfObjectRenderer2D"; -import * as DXFSolidObjectRenderer from "./render2D/dxfSolidObjectRenderer2D"; -import Layer from "../core/layer"; -import Device from "../core/device"; -import Feature from "../core/feature"; -import Params from "../core/params"; -import Component from "../core/component"; -import UIElement from "./uiElement"; -import TextElement from "./textElement"; -import MapUtils from "../utils/mapUtils"; -import { Point, ToolPaperObject } from "../core/init"; -import Connection from "../core/connection"; -import { ViewManager } from ".."; -import Parameter from "../core/parameter"; -import EventBus from "@/events/events"; -/** - * Paper View class - */ -export default class PaperView { - panAndZoom: PanAndZoom; - center: paper.Point; - zoom: number; - canvas: HTMLElement | null; - paperFeatures: any; - paperLayers: any; - paperGrid: paper.Group | null; - paperDevice: paper.Group | null; - activeLayer: any; - gridLayer: paper.Group; - deviceLayer: paper.Group; - featureLayer: paper.Group; - textFeatureLayer: paper.Group; - alignmentMarksLayer: paper.Group; - uiLayer: paper.Group; - ratsNestLayer: paper.Group; - componentPortsLayer: paper.Group; - currentTarget: any; - lastTargetType: string | null; - lastTargetPosition: Point | null; - lastTargetParameters: any; - selectedComponents: Array; - selectedConnections: Array; - inactiveAlpha: number; - private __viewManagerDelegate: any; - featureRegistry: Map; - lastTargetSet: string | null = null; - protected _paperComponentPortView: PaperComponentPortView; - private __ratsNestRender: paper.Group | null = null; - layerMask: any; - alignmentMarks: paper.Group | null = null; - - /** - * Requires the canvas ID to setup the entire application. - * @param {string} canvasID - * @param {} viewmanager - */ - constructor(canvasID: string, viewmanager: ViewManager) { - // Setup the Canvas - paper.setup(canvasID); - - // Get the Canvas Object - const canvas = document.getElementById(canvasID); - - this.panAndZoom = new PanAndZoom(this); - this.center = paper.view.center; - this.zoom = paper.view.zoom; - this.canvas = canvas; - this.paperFeatures = {}; - this.paperLayers = []; - this.paperGrid = null; - this.paperDevice = null; - this.activeLayer = null; - this.gridLayer = new paper.Group(); - this.deviceLayer = new paper.Group(); - this.gridLayer.insertAbove(this.deviceLayer); - this.featureLayer = new paper.Group(); - this.featureLayer.insertAbove(this.gridLayer); - this.textFeatureLayer = new paper.Group(); - this.textFeatureLayer.insertAbove(this.featureLayer); - this.alignmentMarksLayer = new paper.Group(); - this.alignmentMarksLayer.insertAbove(this.textFeatureLayer); - this.uiLayer = new paper.Group(); // This is the layer which we use to render targets - this.uiLayer.insertAbove(this.featureLayer); - this.ratsNestLayer = new paper.Group(); - this.ratsNestLayer.insertAbove(this.featureLayer); - this.componentPortsLayer = new paper.Group(); - this.componentPortsLayer.insertAbove(this.featureLayer); - this.currentTarget = null; - this.lastTargetType = null; - this.lastTargetPosition = null; - this.selectedComponents = []; - this.selectedConnections = []; - this.inactiveAlpha = 0.5; - this.__viewManagerDelegate = viewmanager; - this.featureRegistry = new Map(); - - this._paperComponentPortView = new PaperComponentPortView(this.componentPortsLayer, viewmanager); - - this.disableContextMenu(); - } - - /** - * Returns a list of selected items on the canvas - * @return {Array} - * @memberof PaperView - */ - getSelectedFeatures() { - const output = []; - const items = paper.project.selectedItems; - for (let i = 0; i < items.length; i++) { - // @ts-ignore - output.push(this.__viewManagerDelegate.getFeatureByID(items[i].featureID)); - } - return output; - } - - /** - * Deselects the items from the canvas - * @returns {void} - * @memberof PaperView - */ - clearSelectedItems(): void { - paper.project.deselectAll(); - this.selectedConnections = []; - this.selectedComponents = []; - } - - /** - * Deletes the selected features and selected components from the canvas - * TODO: Rename the method - * @returns {void} - * @memberof PaperView - */ - deleteSelectedFeatures(): void { - // TODO: Refine how this works with the selection object code later on - const items = paper.project.selectedItems; - if (items && items.length > 0) { - for (let i = 0; i < items.length; i++) { - // @ts-ignore - this.__viewManagerDelegate.removeFeatureByID(items[i].featureID); - } - - // Delete the selected Components !!! - let connection; - for (const i in this.selectedComponents) { - connection = this.__viewManagerDelegate.currentDevice.removeComponent(this.selectedComponents[i]); - if (connection) { - this.__viewManagerDelegate.updatesConnectionRender(connection); - } - } - - // Delete the selected Connecitons - for (const i in this.selectedConnections) { - this.__viewManagerDelegate.currentDevice.removeConnection(this.selectedConnections[i]); - } - } - } - - /** - * Selects all active layers in the canvas - * @returns {void} - * @memberof PaperView - */ - selectAllActive(): void { - const layer = this.paperLayers[this.activeLayer]; - for (const i in layer.children) { - layer.children[i].selected = true; - } - } - - /** - * Converts the layers to SVG format - * @memberof PaperView - * @returns {} - */ - layersToSVGStrings() { - const output = []; - for (let i = 0; i < this.featureLayer.children.length; i++) { - const layer = this.featureLayer.children[i]; - const svg = this.postProcessLayerToSVG(layer); - output.push(svg); - } - return output; - } - - /** - * Process layers to SVG - * @param {Layer} layer Layer object - * @returns Returns an SVG format - * @memberof PaperView - */ - postProcessLayerToSVG(layer: paper.Item): string { - // var flip = layer.params["flip"]; - const layerCopy = layer.clone(); - // if (flip === true) { - // layerCopy.scale(-1,1); - // } - layerCopy.bounds.topLeft = new paper.Point(0, 0); - const deviceWidth = this.__viewManagerDelegate.currentDevice.getXSpan(); - const deviceHeight = this.__viewManagerDelegate.currentDevice.getYSpan(); - layerCopy.bounds.topLeft = new paper.Point(0, 0); - layerCopy.bounds.bottomRight = new paper.Point(deviceWidth, deviceHeight); - const svg = layer.exportSVG({ - asString: true - }); - - const width = deviceWidth; - const height = deviceHeight; - const widthInMillimeters = width / 1000; - const heightInMilliMeters = height / 1000; - const prepend = ManufacturingLayer.generateSVGTextPrepend(widthInMillimeters, heightInMilliMeters); - const append = ManufacturingLayer.generateSVGTextAppend(); - const newSVG = prepend + svg + append; - layerCopy.remove(); - return newSVG; - } - - /** - * Gets the width of the canvas - * @returns {number} Returns the width of the canvas - * @memberof PaperView - */ - getCanvasWidth(): number { - if (this.canvas === null) { - throw new Error("Canvas is null"); - } - return this.canvas.clientWidth; - } - - /** - * Gets the height of the canvas - * @returns {number} Returns the height of the canvas - * @memberof PaperView - */ - getCanvasHeight(): number { - if (this.canvas === null) { - throw new Error("Canvas is null"); - } - return this.canvas.clientHeight; - } - - /** - * Gets the view of the center in mm - * @returns {number} - * @memberof PaperView - */ - getViewCenterInMillimeters() { - return [paper.view.center.x / 1000, paper.view.center.y / 1000]; - } - - /** - * Gets the device height in pixels - * @returns {number} - * @memberof PaperView - */ - getDeviceHeightInPixels(): number { - return this.__viewManagerDelegate.currentDevice.getYSpan() * paper.view.zoom; - } - - /** - * Clears the all the paper group collections stored in the paperview object. Used when everything has to be - * redrawn - * @returns {void} - * @memberof PaperView - */ - clear(): void { - this.activeLayer = null; - this.featureLayer.removeChildren(); - this.deviceLayer.removeChildren(); - this.gridLayer.removeChildren(); - this.alignmentMarksLayer.removeChildren(); - } - - /** - * Gets the center of the paper - * @returns {Array} - * @memberof PaperView - */ - getCenter(): paper.Point { - return this.center; - } - - /** - * Sets the center at a specific point of the canvas - * @param {Array} point X and Y coordinates - * @returns {void} - * @memberof PaperView - */ - setCenter(point: paper.Point): void { - this.center = point; - this.updateCenter(); - } - - /** - * Updates the paper center to the new value - * @returns {void} - * @memberof PaperView - */ - updateCenter(): void { - paper.view.center = this.center; - } - - /** - * Gets the zoom at the paper - * @returns {number} Returns zoom value - * @memberof PaperView - */ - getZoom(): number { - return this.zoom; - } - - /** - * Sets a specific zoom at the paper view - * @param {number} zoom Zoom value - * @returns {void} - * @memberof PaperView - */ - setZoom(zoom: number): void { - this.zoom = zoom; - this.updateZoom(); - - //sends out the update zoom event - EventBus.get().emit(EventBus.UPDATE_ZOOM); - } - - /** - * Updates zoom of the canvas - * @returns {void} - * @memberof PaperView - */ - updateZoom(): void { - paper.view.zoom = this.zoom; - } - - /** - * Returns the coordinates of the project - * @param {number} x X coordinate of the canvas - * @param {number} y Y coordinate of the canvas - * @returns {} - * @memberof PaperView - */ - canvasToProject(x: number, y: number) { - if (this.canvas === null) { - throw new Error("Canvas is null"); - } - const rect = this.canvas.getBoundingClientRect(); - const projX = x - rect.left; - const projY = y - rect.top; - return paper.view.viewToProject(new paper.Point(projX, projY)); - } - - /** - * Converts from canvas to project position - * @param {number} x X coordinate - * @param {number} y Y coordinate - * @returns {} - * @memberof PaperView - */ - getProjectPosition(x: number, y: number) { - return this.canvasToProject(x, y); - } - - /** - * Adds an event listener to the mouse wheel key - * @param {Function} func Event to execute - * @returns {void} - * @memberof PaperView - */ - setMouseWheelFunction(func: { (event: any): void; (event: any): void; (this: HTMLElement, ev: WheelEvent): any }): void { - if (this.canvas === null) { - throw new Error("Canvas is null"); - } - this.canvas.addEventListener("wheel", func); - } - - /** - * Adds an event listener when the mouse goes down - * @param {Function} func Event to execute - * @returns {void} - * @memberof PaperView - */ - setMouseDownFunction(func: ((this: GlobalEventHandlers, ev: MouseEvent) => any) | null): void { - if (this.canvas === null) { - throw new Error("Canvas is null"); - } - this.canvas.onmousedown = func; - } - - /** - * Adds an event listener to the mouse up key - * @param {Function} func Event to execute - * @returns {void} - * @memberof PaperView - */ - setMouseUpFunction(func: ((this: GlobalEventHandlers, ev: MouseEvent) => any) | null): void { - if (this.canvas === null) { - throw new Error("Canvas is null"); - } - this.canvas.onmouseup = func; - } - - /** - * Adds an event listener when the mouse moves - * @param {Function} func Event to execute - * @returns {void} - * @memberof PaperView - */ - setMouseMoveFunction(func: ((this: GlobalEventHandlers, ev: MouseEvent) => any) | null): void { - if (this.canvas === null) { - throw new Error("Canvas is null"); - } - this.canvas.onmousemove = func; - } - - /** - * Adds an event listener when a key is press - * @param {Function} func Event to execute - * @returns {void} - * @memberof PaperView - */ - setKeyPressFunction(func: ((this: GlobalEventHandlers, ev: KeyboardEvent) => any) | null): void { - if (this.canvas === null) { - throw new Error("Canvas is null"); - } - this.canvas.onkeypress = func; - } - - /** - * Adds an event listener when a key is down - * @param {Function} func Event to execute - * @returns {void} - * @memberof PaperView - */ - setKeyDownFunction(func: ((this: GlobalEventHandlers, ev: KeyboardEvent) => any) | null): void { - if (this.canvas === null) { - throw new Error("Canvas is null"); - } - this.canvas.onkeydown = func; - } - - /** - * Sets the resize function - * @param {Function} func Event to execute - * @returns {void} - * @memberof PaperView - */ - setResizeFunction(func: () => void | null): void { - if (this.canvas === null) { - throw new Error("Canvas is null"); - } - paper.view.onResize = func; - } - - /** - * Disables the contex menu - * @param {Function} func Event to execute - * @returns {void} - * @memberof PaperView - */ - disableContextMenu(): void { - if (this.canvas === null) { - throw new Error("Canvas is null"); - } - this.canvas.oncontextmenu = function(event) { - event.preventDefault(); - }; - } - - /** - * Refreshes the view of the paper - * @returns {void} - * @memberof PaperView - */ - refresh(): void { - paper.view.update(); - } - - /* Rendering Devices */ - /** - * Renders device - * @param {Device} device Device object - * @returns {void} - * @memberof PaperView - */ - addDevice(device: Device): void { - this.updateDevice(device); - } - - /** - * Updates a device - * @param {Device} device Device object - * @returns {void} - * @memberof PaperView - */ - updateDevice(device: Device): void { - this.removeDevice(); - const newPaperDevice = DeviceRenderer.renderDevice(device); - this.paperDevice = newPaperDevice; - this.deviceLayer.addChild(newPaperDevice); - } - - /** - * Removes the device from the paper - * @returns {void} - * @memberof PaperView - */ - removeDevice(): void { - if (this.paperDevice) this.paperDevice.remove(); - this.paperDevice = null; - //TODO: Figure out how to handle featureRegistry - //this.featureRegistry = new Map(); - } - - /* Rendering Layers */ - /** - * Renders the layers - * @param {Layer} layer Layer object - * @param {number} index Index of layer to render (Int) - * @returns {void} - * @memberof PaperView - */ - addLayer(layer: Layer, index: number): void { - this.paperLayers[index] = new paper.Group(); - this.featureLayer.addChild(this.paperLayers[index]); - // this.setActiveLayer(index); - } - - - /** - * Delete the layer from the paperview at the given index. - * @param {number} index Index of the layer to be removed (Int) - * @returns {void} - * @memberof PaperView - */ - removeLayer(index: number): void { - if (index !== -1) { - for (let i = 0; i < this.paperLayers[index].children.length; i++) { - this.featureRegistry.delete(this.paperLayers[index].children[i].featureID); - } - this.paperLayers.splice(index, 1); - } - } - - /* Rendering Features */ - /** - * Renders a feature - * @param {Feature} feature Feature to be render - * @returns {void} - * @memberof PaperView - */ - addFeature(feature: Feature): void { - this.updateFeature(feature); - } - - /** - * Sets a new active layer - * @param {number} index Index of layer to be active (Int) - * @returns {void} - * @memberof PaperView - */ - setActiveLayer(index: number): void { - this.activeLayer = index; - if (this.activeLayer !== null && this.activeLayer >= 0) this.showActiveLayer(); - } - - /** - * Show the current active layer - * @returns {void} - * @memberof PaperView - */ - showActiveLayer(): void { - this.featureLayer.remove(); - this.featureLayer = new paper.Group(); - for (let i = 0; i < this.paperLayers.length; i++) { - this.featureLayer.addChild(this.paperLayers[i]); - } - if (this.layerMask) this.layerMask.remove(); - this.layerMask = DeviceRenderer.renderLayerMask(this.__viewManagerDelegate.currentDevice); - this.featureLayer.addChild(this.layerMask); - const activeLayer = this.paperLayers[this.activeLayer]; - activeLayer.bringToFront(); - } - - /** - * Show only the desired features - * Chosen features appear - * Built for use in uF Guide Tool - * @param {Array} features Array of features to be displayed - * @returns {void} - * @memberof PaperView - */ - showChosenFeatures(features: Array): void { - this.resetFeatureLayers(); - this.featureLayer.remove(); - this.featureLayer = new paper.Group(); - for (let i = 0; i < this.paperLayers.length; i++) { - this.featureLayer.addChild(this.paperLayers[i]); - } - if (this.layerMask) this.layerMask.remove(); - this.layerMask = DeviceRenderer.renderLayerMask(this.__viewManagerDelegate.currentDevice); - this.featureLayer.addChild(this.layerMask); - const activeLayer = new paper.Group(); - for (let i = 0; i < features.length; i++) { - activeLayer.addChild(features[i]); - } - activeLayer.bringToFront(); - - const textLayer = this.getNonphysText(); - textLayer.bringToFront(); - } - - /** - * Show all but the desired features - * Chosen features behind mask - * Built for use in uF Guide Tool - * @param {Array} features Array of features to be displayed - * @returns {void} - * @memberof PaperView - */ - hideChosenFeatures(features: Array): void { - this.resetFeatureLayers(); - this.featureLayer.remove(); - this.featureLayer = new paper.Group(); - if (this.layerMask) this.layerMask.remove(); - this.layerMask = DeviceRenderer.renderLayerMask(this.__viewManagerDelegate.currentDevice); - this.featureLayer.addChild(this.layerMask); - for (let i = 0; i < this.paperLayers.length; i++) { - this.featureLayer.addChild(this.paperLayers[i]); - } - const activeLayer = new paper.Group(); - for (let i = 0; i < features.length; i++) { - activeLayer.addChild(features[i]); - } - activeLayer.insertAbove(this.gridLayer); - - const textLayer = this.getNonphysText(); - textLayer.bringToFront(); - } - - /** - * Display all features in the device - * Built for use in uF Guide Tool - * @returns {void} - * @memberof PaperView - */ - showAllFeatures(): void { - this.resetFeatureLayers(); - this.featureLayer.remove(); - this.featureLayer = new paper.Group(); - if (this.layerMask) this.layerMask.remove(); - this.layerMask = DeviceRenderer.renderLayerMask(this.__viewManagerDelegate.currentDevice); - this.featureLayer.addChild(this.layerMask); - for (let i = 0; i < this.paperLayers.length; i++) { - this.featureLayer.addChild(this.paperLayers[i]); - } - - const textLayer = this.getNonphysText(); - textLayer.bringToFront(); - } - - /** - * Return all features to the paper layers defined in featureRegistry - * Built for use in uF Guide Tool - * @returns {void} - * @memberof PaperView - */ - resetFeatureLayers(): void { - for (let i = 0; i < this.paperLayers.length; i++) { - this.featureRegistry.forEach((value, key) => { - if (this.paperLayers[i].id == value) { - this.paperLayers[i].addChild(this.paperFeatures[key]); - } - }); - } - } - - /** - * Brings nonphysical text features to the front - * Ensures nonphysical text is on top of device features - * Built for use in uF Guide Tool - * @returns {void} - * @memberof PaperView - */ - getNonphysText() { - if (Registry.viewManager === undefined || Registry.viewManager === null) { - throw new Error("Registry.viewManager is undefined"); - } - const textLayer = new paper.Group(); - const nonphysElements = Registry.viewManager.nonphysElements; - for (let i = 0; i < nonphysElements.length; i++) { - for (const j in this.paperFeatures) { - if (nonphysElements[i].type == "Text" && nonphysElements[i].featureIDs.includes(this.paperFeatures[j].featureID)) { - textLayer.addChild(this.paperFeatures[j]); - } - } - } - return textLayer; - } - - /** - * Generate nonphysical text - * Text color can be set to black, white, red, or blue - * Built for use in uF Guide Tool - * @param {string} text Text to be displayed - * @param {[number,number]} position Coordinates on the canvas grid - * @param {number} size Font size - * @param {string} color The color of the text - * @param {number} layer The layer on which - * @returns {void} - * @memberof PaperView - */ - generateNonphysText(text: string, position: paper.Point, size: number, color: any, layer = this.activeLayer): void { - const newFeature = Device.makeFeature( - "Text", - { - position: position, - height: 20, - text: text, - fontSize: size, - color: color - }, - "TEXT_" + text, - uuid.v1(), - "XY", - null - ); - this.__viewManagerDelegate.addFeature(newFeature, layer, false); - // this.addComponent("Text", newFeature.getParams(), [newFeature.ID], false); - const element = this.addUIElement("Text", newFeature.getParams(), [newFeature.ID]); - newFeature.referenceID = element.id; - this.__viewManagerDelegate.saveDeviceState(); - } - - /** - * Creates a new UIElement and adds it to viewManager's nonphysicalElements array - * Note: Takes the feature ids as an array - * TODO: Modify this to take the MINT String as another parameter - * Built for use in uF Guide Tool - * @param typeString Type of the Feature - * @param params Map of all the paramters - * @param featureIDs [String] Feature id's of all the features that will be a part of this component - */ - addUIElement(typeString: string, paramdata: { [index: string]: Parameter }, featureIDs: Array) { - if (Registry.viewManager === undefined || Registry.viewManager === null) { - console.log("ViewManager is not defined"); - throw new Error("ViewManager is not defined"); - } - let newElement; - if (typeString == "Text") { - newElement = new TextElement(typeString, paramdata, featureIDs); - } else { - newElement = new UIElement(); - // TODO: implement parameter handling for base UIElement - } - Registry.viewManager.nonphysElements.push(newElement); - return newElement; - } - - /** - * Inserts paper feature into the UILayer - * Built for use in uF Guide Tool - * @param newPaperFeature Paper feature to be added to the UI layer - */ - insertUIFeature(newPaperFeature: paper.Item): void { - this.uiLayer.insertChild(0, newPaperFeature); - } - - /** - * Creates a new component and adds it to viewManager's nonphysicalComponents or the currentDevice's __components - * Note: Takes the feature ids as an array - * TODO: Modify this to take the MINT String as another parameter - * Built for use in uF Guide Tool - * @param typeString Type of the Feature - * @param params Map of all the paramters - * @param featureIDs [String] Feature id's of all the features that will be a part of this component - * @param physical Boolean stating whether feature physical or not - */ - addComponent(typeString: string, paramdata: { [index: string]: Parameter }, featureIDs: Array, physical: boolean) { - if (Registry.viewManager === undefined || Registry.viewManager === null) { - console.error("ViewManager is not defined"); - throw new Error("ViewManager is not defined"); - } - if (Registry.currentDevice === undefined || Registry.currentDevice === null) { - console.error("Current Device is not defined"); - throw new Error("Current Device is not defined"); - } - const definition = ComponentAPI.getDefinition(typeString); - if (definition === undefined || definition === null) { - throw new Error("Component definition not found"); - } - // Clean Param Data - const cleanparamdata: { [key: string]: any } = {}; - for (const key in paramdata) { - cleanparamdata[key] = paramdata[key].value; - } - const params = new Params(cleanparamdata, MapUtils.toMap(definition.unique), MapUtils.toMap(definition.heritable)); - const componentid = ComponentAPI.generateID(); - const name = Registry.currentDevice.generateNewName(typeString); - const newComponent = new Component(params, name, definition.mint, componentid); - let feature; - - for (const i in featureIDs) { - newComponent.addFeatureID(featureIDs[i]); - - // Update the component reference - feature = this.__viewManagerDelegate.getFeatureByID(featureIDs[i]); - feature.referenceID = componentid; - } - - Registry.currentDevice.addComponent(newComponent); - return newComponent; - } - - /** - * Compares feature heights of the paper - * @param {number} a - * @param {number} b - * @returns {number} - * @memberof PaperView - */ - comparePaperFeatureHeights(a: { featureID: any }, b: { featureID: any }): number { - let bHeight; - let aHeight; - const aFeature = this.__viewManagerDelegate.getFeatureByID(a.featureID); - const bFeature = this.__viewManagerDelegate.getFeatureByID(b.featureID); - - // TODO: So this needs to be eliminated form the entire sequence - try { - aHeight = aFeature.getValue("height"); - } catch (e) { - aHeight = 9999; - } - - try { - bHeight = bFeature.getValue("height"); - } catch (e) { - bHeight = 9999; - } - return aHeight - bHeight; - } - - /** - * Insert a child component by height order - * @param {*} group - * @param {*} newChild - * @returns {void} - * @memberof PaperView - */ - insertChildByHeight(group: { children: string | any[]; insertChild: (arg0: any, arg1: any) => void }, newChild: any): void { - let index; - if (group.children.length > 0) { - index = this.getIndexByHeight(group.children, newChild); - } else { - index = 0; - } - group.insertChild(index, newChild); - } - - // TODO: Could be done faster with a binary search. Probably not needed! - /** - * Gets the index of a children component depending on it's height - * @param {*} children - * @param {*} newChild - * @returns {number} Returns the index of the component - * @memberof PaperView - */ - getIndexByHeight(children: string | any[], newChild: any): number { - for (let i = 0; i < children.length; i++) { - const test = this.comparePaperFeatureHeights(children[i], newChild); - if (test >= 0) { - return i; - } - } - return children.length; - } - - /** - * Updates the selected featured - * @param {Feature} feature Feature object - * @returns {void} - * @memberof PaperView - */ - updateFeature(feature: Feature): void { - const existingFeature = this.paperFeatures[feature.ID]; - let selected; - if (existingFeature) selected = existingFeature.selected; - else selected = false; - this.removeFeature(feature); - let newPaperFeature; - // if (!Registry.currentDevice.containsFeatureID(feature.ID)) { - // newPaperFeature = FeatureRenderer2D.renderFeature(feature); - // this.insertUIFeature(newPaperFeature); - // } else { - if (feature instanceof EdgeFeature) { - newPaperFeature = DXFObjectRenderer2D.renderEdgeFeature(feature); - newPaperFeature.selected = selected; - // @ts-ignore - this.paperFeatures[newPaperFeature.featureID] = newPaperFeature; - this.insertEdgeFeatures(newPaperFeature); - return; - } else { - newPaperFeature = FeatureRenderer2D.renderFeature(feature, null); - } - newPaperFeature.selected = selected; - this.paperFeatures[newPaperFeature.featureID] = newPaperFeature; - const index = this.__viewManagerDelegate.renderLayers.indexOf(this.__viewManagerDelegate.getRenderLayerByID(feature.ID)); - const layer = this.paperLayers[index]; - this.insertChildByHeight(layer, newPaperFeature); - this.featureRegistry.set(newPaperFeature.featureID, layer.id); - // } - } - - /** - * Removes the target that is being rendered - * @returns {void} - * @memberof PaperView - */ - removeTarget(): void { - if (this.currentTarget) this.currentTarget.remove(); - this.currentTarget = null; - } - - /** - * Add information about the target that has to be rendered - * @param {string} featureType String that identifies what kind of a feature this is - * @param {Feature} set Feature set the feature belongs to - * @param {Array} position x,y position of the feature - * @returns {void} - * @memberof PaperView - */ - addTarget(featureType: string | null, set: string, position: Point | null, currentParameters: any): void { - this.removeTarget(); - this.lastTargetParameters = currentParameters; - this.lastTargetType = featureType; - this.lastTargetPosition = position; - this.lastTargetSet = set; - this.updateTarget(); - } - - /** - * Updates the target that being rendered. This entails removing the current target and - * then creates a new target at the new position. - * @returns {void} - * @memberof PaperView - */ - updateTarget(): void { - if (this.__viewManagerDelegate.currentLayer === null){ - console.error("No layer selected"); - throw new Error("No layer selected"); - } - this.removeTarget(); - if (this.lastTargetType && this.lastTargetPosition) { - // Checks if the target is a text type target - if (this.lastTargetType === "TEXT") { - this.currentTarget = FeatureRenderer2D.renderTextTarget(this.lastTargetType, this.lastTargetPosition); - this.uiLayer.addChild(this.currentTarget); - } else if (this.lastTargetSet === "Custom") { - const customcomponent = this.__viewManagerDelegate.customComponentManager.getCustomComponent(this.lastTargetType); - // @ts-ignore - const params = Registry.featureDefaults[this.lastTargetSet][this.lastTargetType]; - params.position = this.lastTargetPosition; - params.color = Colors.getDefaultFeatureColor(this.lastTargetType, this.__viewManagerDelegate.currentLayer); - this.currentTarget = DXFSolidObjectRenderer.renderCustomComponentTarget(customcomponent, params); - this.uiLayer.addChild(this.currentTarget); - } else { - this.currentTarget = FeatureRenderer2D.renderTarget(this.lastTargetType, this.lastTargetPosition, this.lastTargetParameters); - this.uiLayer.addChild(this.currentTarget); - } - } - } - - /** - * Removes a feature - * @param {Feature} feature Feature to be removed - * @returns {void} - * @memberof PaperView - */ - removeFeature(feature: Feature): void { - const paperFeature = this.paperFeatures[feature.ID]; - if (paperFeature) { - paperFeature.remove(); - } - this.paperFeatures[feature.ID] = null; - this.featureRegistry.delete(feature.ID); - } - - /** - * Removes grid of the paper - * @returns {void} - * @memberof PaperView - */ - removeGrid(): void { - if (this.paperGrid) this.paperGrid.remove(); - this.paperGrid = null; - } - - /** - * Updates the grid of the paper - * @param {*} grid Grid to update - * @returns {void} - * @memberof PaperView - */ - updateGrid(grid: any): void { - this.removeGrid(); - const newPaperGrid = GridRenderer.renderGrid(grid); - this.paperGrid = newPaperGrid; - this.gridLayer.addChild(newPaperGrid); - } - - /** - * Updates alignment marks of the paper - */ - updateAlignmentMarks(): void { - // TODO: Update this for the new visualizations - // Remove current Alignment Marks: - // this.removeAlignmentMarks(); - // let newAlignmentMarks = AlignmentRenderer.renderAlignmentMarks(this.lastTargetPosition, 20000, this.paperFeatures); - // this.alignmentMarks = newAlignmentMarks; - // this.alignmentMarksLayer.addChild(newAlignmentMarks); - } - - /** - * Removes alignment marks of the paper - * @returns {void} - * @memberof PaperView - */ - removeAlignmentMarks(): void { - // Does nothing right now - if (this.alignmentMarks) this.alignmentMarks.removeChildren(); - this.alignmentMarks = null; - } - - /** - * Updates unrouted connections of the paper - * @returns {void} - * @memberof PaperView - */ - updateRatsNest(): void { - this.removeRatsNest(); - const unrouted = this.__viewManagerDelegate.currentDevice.getUnroutedConnections(); - - const rendergroup = RatsNestRenderer2D.renderRatsNest(unrouted, this.__viewManagerDelegate.currentDevice); - - this.__ratsNestRender = rendergroup; - this.ratsNestLayer.addChild(this.__ratsNestRender); - } - - /** - * Removes unrouted connections of the paper - * @returns {void} - * @memberof PaperView - */ - removeRatsNest(): void { - // First clear out the render objects - if (this.__ratsNestRender) { - this.__ratsNestRender.remove(); - } - // Next set it to null - this.__ratsNestRender = null; - } - - /** - * Moves the center by a specific value - * @param {number} delta - * @returns {void} - * @memberof PaperView - */ - moveCenter(delta: paper.Point): void { - this.panAndZoom.moveCenter(delta); - } - - /** - * Adjust the zoom bu a specific value to a certain point on the paper - * @param {number} delta - * @param {Array} point - * @returns {void} - * @memberof PaperView - */ - adjustZoom(delta: number, point: paper.Point): void { - this.panAndZoom.adjustZoom(delta, point); - } - - /** - * Gets the paper features - * @param {Array} paperFeatures - * @returns {Array} Returns an array with the features - * @memberof PaperView - */ - getFeaturesByViewElements(paperFeatures: string | any[]) { - const output = []; - for (let i = 0; i < paperFeatures.length; i++) { - output.push(this.__viewManagerDelegate.getFeatureByID(paperFeatures[i].featureID)); - } - return output; - } - - /** - * Initialize the view on the paper - * @returns {void} - * @memberof PaperView - */ - initializeView(): void { - const center = this.getDeviceCenter(); - const zoom = this.computeOptimalZoom(); - this.setCenter(center); - this.setZoom(zoom); - } - - /** - * Centers the device on the paper - * @returns {Array} Returns an array with the X and Y coordinates of the center - * @memberof PaperView - */ - getDeviceCenter() { - const width = this.__viewManagerDelegate.currentDevice.getXSpan(); - const height = this.__viewManagerDelegate.currentDevice.getYSpan(); - return new paper.Point(width / 2, height / 2); - } - - /** - * Calculates the optimal zoom of the paper - * @returns {number} Returns the value of the optima zoom - * @memberof PaperView - */ - computeOptimalZoom(): number { - const borderMargin = 200; // pixels - const deviceWidth = this.__viewManagerDelegate.currentDevice.getXSpan(); - const deviceHeight = this.__viewManagerDelegate.currentDevice.getYSpan(); - const canvasWidth = this.getCanvasWidth(); - const canvasHeight = this.getCanvasHeight(); - let maxWidth; - let maxHeight; - if (canvasWidth - borderMargin <= 0) maxWidth = canvasWidth; - else maxWidth = canvasWidth - borderMargin; - if (canvasHeight - borderMargin <= 0) maxHeight = canvasHeight; - else maxHeight = canvasHeight - borderMargin; - const widthRatio = deviceWidth / maxWidth; - const heightRatio = deviceHeight / maxHeight; - if (widthRatio > heightRatio) { - return 1 / widthRatio; - } else { - return 1 / heightRatio; - } - } - - /** - * Checks to see if the point intersects with any feature that is rendered on the canvas - * @param {Array} point X and Y coordinates of the point - * @param {boolean} onlyHitActiveLayer Default to true - * @return {boolean} Rendered Feature - * @memberof PaperView - */ - hitFeature(point: paper.Point, onlyHitActiveLayer = true, nonphysActiveLayer = false) { - const hitOptions = { - fill: true, - tolerance: 5, - guides: false - }; - - let target; - - if (onlyHitActiveLayer && this.activeLayer !== null && !nonphysActiveLayer) { - target = this.paperLayers[this.activeLayer]; - - const result = target.hitTest(point, hitOptions); - if (result) { - return result.item; - } - } else if (onlyHitActiveLayer && nonphysActiveLayer) { - target = this.getNonphysText(); - - const result = target.hitTest(point, hitOptions); - if (result) { - return result.item; - } - } else { - for (let i = this.paperLayers.length - 1; i >= 0; i--) { - target = this.paperLayers[i]; - const result = target.hitTest(point, hitOptions); - if (result) { - return result.item; - } - } - } - return null; - } - - /** - * Checks if the feature hit an element ? - * @param {*} paperElement - * @param {*} onlyHitActiveLayer - * @returns {Array} Returns an Array with all the child components which intersects the paper element - * @memberof PaperView - */ - hitFeaturesWithViewElement(paperElement: any, onlyHitActiveLayer = true) { - const output = []; - if (onlyHitActiveLayer && this.activeLayer !== null) { - const layer = this.paperLayers[this.activeLayer]; - for (let i = 0; i < layer.children.length; i++) { - const child = layer.children[i]; - if (paperElement.intersects(child) || child.isInside(paperElement.bounds)) { - output.push(child); - } - } - } else { - for (let i = 0; i < this.paperLayers.length; i++) { - const layer = this.paperLayers[i]; - for (let j = 0; j < layer.children.length; j++) { - const child = layer.children[j]; - if (paperElement.intersects(child) || child.isInside(paperElement.bounds)) { - output.push(child); - } - } - } - } - return output; - } - - /** - * Inserts new feature to the edge - * @param {Feature} newPaperFeature Feature to be inserted - * @returns {void} - * @memberof PaperView - */ - insertEdgeFeatures(newPaperFeature: paper.CompoundPath): void { - const layer = this.paperLayers[0]; - layer.insertChild(0, newPaperFeature); - } - - /** - * Returns the rendered feature object that is being displayed for the particular feature - * @param {string} featureID ID of the feature - * @return {ToolPaperObject} Returns an object containing the rendered features - * @memberof PaperView - */ - getRenderedFeature(featureID: string) { - return this.paperFeatures[featureID]; - } - - /** - * Updates the component after it was rendered - * @returns {void} - * @memberof PaperView - */ - updateComponentPortsRender(): void { - this._paperComponentPortView.updateRenders(); - } - - /** - * Enable snap render - * @returns {void} - * @memberof PaperView - */ - enableSnapRender(): void { - this._paperComponentPortView.enable(); - } - - /** - * Disable snap render - * @returns {void} - * @memberof PaperView - */ - disableSnapRender(): void { - this._paperComponentPortView.disable(); - } - - /** - * Returns the paperjs object that is rendering the feature - * @param {string} featureID - * @returns - */ - getRender(featureID: string) { - return this.paperFeatures[featureID]; - } -} diff --git a/src/app/view/render2D/alignmentRenderer2D.ts b/src/app/view/render2D/alignmentRenderer2D.ts deleted file mode 100644 index 0f9e6f66..00000000 --- a/src/app/view/render2D/alignmentRenderer2D.ts +++ /dev/null @@ -1,83 +0,0 @@ -import * as Colors from "../colors"; -import Feature from "../../core/feature"; -import paper from "paper"; -import { Point } from "@/app/core/init"; - -function getLayerColor(feature: any) { - const height = feature.getValue("height"); - const layerHeight = 1; // feature.layer.estimateLayerHeight(); - let decimal = height / layerHeight; - if (decimal > 1) decimal = 1; - if (!feature.layer.flip) decimal = 1 - decimal; - const targetColorSet = Colors.getLayerColors(feature.layer); - return Colors.decimalToLayerColor(decimal, targetColorSet, Colors.darkColorKeys); -} - -function getBaseColor(feature:any) { - let decimal = 0; - if (!feature.layer.flip) decimal = 1 - decimal; - const targetColorSet = Colors.getLayerColors(feature.layer); - return Colors.decimalToLayerColor(decimal, targetColorSet, Colors.darkColorKeys); -} - -function calculateDistance(pointer_position: Point, feature_position: paper.Point) { - return Math.sqrt(Math.pow(pointer_position[0] - feature_position.x, 2) + Math.pow(pointer_position[1] - feature_position.y, 2)); -} - -export function renderAlignmentMarks(position: Point, radius: number, features: Array) { - // let renderer = getFeatureRenderer(typeString, setString); - // let params = renderer.targetParams; - // let prim = getPrimitive2D(renderer.targetPrimitiveType, renderer.targetPrimitiveSet); - // let primParams = {}; - // for (let key in params) { - // primParams[key] = getDefaultValueForType(typeString, setString, params[key]); - // } - // primParams["position"] = position; - // primParams["color"] = Colors.getDefaultFeatureColor(typeString, setString, Registry.currentLayer); - // let rendered = prim(primParams); - const alignmentmarkergroup = new paper.Group(); - - for (const i in features) { - const feature = features[i]; - if (feature === null) { - continue; - } - if (calculateDistance(position, feature.getBounds().center) < radius) { - // TODO: figure out how check for different kinds of components and then generate - - // Generate the alignment H | V lines for each of the features - - // Get the bounds of the feature - - const bounds = feature.getBounds(); - - // Only the centroid alignment marks - const center = bounds.center; - const hstart = new paper.Point(center.x - radius, center.y); - const hend = new paper.Point(center.x + radius, center.y); - - const vstart = new paper.Point(center.x, center.y - radius); - const vend = new paper.Point(center.x, center.y + radius); - - const hpath = new paper.Path([hstart, hend]); - const vpath = new paper.Path([vstart, vend]); - - hpath.strokeColor = new paper.Color("#696965"); - hpath.strokeWidth = 500; - hpath.strokeCap = "round"; - - hpath.dashArray = [1000, 1200]; - - vpath.strokeColor = new paper.Color("#696965"); - vpath.strokeWidth = 500; - vpath.strokeCap = "round"; - - vpath.dashArray = [1000, 1200]; - - alignmentmarkergroup.addChild(vpath); - alignmentmarkergroup.addChild(hpath); - } - } - - return alignmentmarkergroup; -} diff --git a/src/app/view/render2D/componentPortRenderer2D.ts b/src/app/view/render2D/componentPortRenderer2D.ts deleted file mode 100644 index 47285d65..00000000 --- a/src/app/view/render2D/componentPortRenderer2D.ts +++ /dev/null @@ -1,54 +0,0 @@ -import * as Colors from "../colors"; -import paper from "paper"; -import Registry from "../../core/registry"; -import Component from "@/app/core/component"; -import ComponentPort from "@/app/core/componentPort"; -import { Point } from "@/app/core/init"; - -export default class ComponentPortRenderer2D { - static renderComponentPort(componentport: ComponentPort, draworigin: Point, rotation: number, portrendersize: number = 500) { - const xpos = draworigin[0]; - const ypos = draworigin[1]; - const point = new paper.Point(xpos + componentport.x, ypos + componentport.y); - - const circle = new paper.Path.Circle(point, portrendersize); - - circle.rotate(rotation, new paper.Point(draworigin[0], draworigin[1])); - - circle.fillColor = new paper.Color(Colors.BLACK); - - return circle; - } - - static getSizeforZoomLevel() { - const zoomlevel = paper.view.zoom; - let ret = 5 / zoomlevel; - if (ret > 500) { - ret = 500; - } - return ret; - } - - static renderComponentPorts(component: Component) { - const rendersize = ComponentPortRenderer2D.getSizeforZoomLevel(); - const componentports = component.ports; - const ret = []; - const rotation = component.getRotation(); - const currPos = component.getValue("position"); - component.setOffset(); - const position: Point = [currPos[0] - component.offset[0], currPos[1] - component.offset[1]]; - for (const key of componentports.keys()) { - const componentport = componentports.get(key); - if (componentport === undefined) { - console.error(`component ${component.id} has no port ${key}`); - continue; - } - const render = ComponentPortRenderer2D.renderComponentPort(componentport, position, rotation, rendersize); - // TODO - Figure out how to fix this or keep track of this - // render["renderid"] = componentport.id; - component.attachComponentPortRender(key, render); - ret.push(render); - } - return ret; - } -} diff --git a/src/app/view/render2D/deviceRenderer2D.ts b/src/app/view/render2D/deviceRenderer2D.ts deleted file mode 100644 index dc6b9917..00000000 --- a/src/app/view/render2D/deviceRenderer2D.ts +++ /dev/null @@ -1,44 +0,0 @@ -import * as Colors from "../colors"; // pixels -import paper from "paper"; -import Device from "@/app/core/device"; -const DEFAULT_STROKE_COLOR = Colors.GREY_700; -const BORDER_THICKNESS = 5; - -export default class DeviceRenderer { - static renderLayerMask(device: Device) { - const width = device.getXSpan(); - const height = device.getYSpan(); - let fillColor = new paper.Color(Colors.WHITE); - fillColor.alpha = 0.5; - const mask = new paper.Path.Rectangle({ - from: new paper.Point(0, 0), - to: new paper.Point(width, height), - fillColor: fillColor, - strokeColor: null - }); - return mask; - } - - static renderDevice(device: Device, strokeColor = DEFAULT_STROKE_COLOR) { - const background = new paper.Path.Rectangle({ - from: paper.view.bounds.topLeft.subtract(new paper.Point(paper.view.size)), - to: paper.view.bounds.bottomRight.add(new paper.Point(paper.view.size)), - fillColor: new paper.Color(Colors.BLUE_50), - strokeColor: null - }); - const thickness = BORDER_THICKNESS / paper.view.zoom; - const xspan = device.getXSpan(); - const yspan = device.getYSpan(); - const border = new paper.Path.Rectangle({ - from: new paper.Point(0, 0), - to: new paper.Point(xspan, yspan), - fillColor: Colors.WHITE, - strokeColor: strokeColor, - strokeWidth: thickness - }); - - const group = new paper.Group([background, border]); - - return group; - } -} diff --git a/src/app/view/render2D/dxfObjectRenderer2D.ts b/src/app/view/render2D/dxfObjectRenderer2D.ts deleted file mode 100644 index 5ec84dfb..00000000 --- a/src/app/view/render2D/dxfObjectRenderer2D.ts +++ /dev/null @@ -1,392 +0,0 @@ -import * as THREE from "three"; -import paper from "paper"; - -import edgeFeature from "@/app/core/edgeFeature"; - -export function renderFeatureObjects(feature: any) { - throw new Error("Implement the renderer"); - - // console.log("rendering the features dxf objects"); - // for (const i in feature.getDXFObjects()) { - // const dxfobject = feature.getDXFObjects()[i]; - // } - // return undefined; -} - -/** - * Returns a PaperJS outline rendering of the given - * DXF objects contained in the feature. - * @param feature - */ -export function renderEdgeFeature(feature: edgeFeature) { - const path = new paper.CompoundPath(""); - - // console.log('rendering the outline dxf objects....', feature.getDXFObjects()); - for (const i in feature.getDXFObjects()) { - const dxfobject = feature.getDXFObjects()[i]; - // Figure out what entity this is and then based on that do the drawing - let mesh; - if (dxfobject.getType() === "ARC") { - drawArc(dxfobject.getData(), path); - } else if (dxfobject.getType() === "LWPOLYLINE" || dxfobject.getType() === "LINE" || dxfobject.getType() === "POLYLINE") { - drawLine(dxfobject.getData(), path); - } else if (dxfobject.getType() === "SPLINE") { - drawSpline(dxfobject.getData(), path); - } else if (dxfobject.getType() === "ELLIPSE") { - drawEllipse(dxfobject.getData(), path); - } else if (dxfobject.getType() === "CIRCLE") { - drawCircle(dxfobject.getData(), path); - } else { - console.error("Unsupported DXF Entity Type for Outline Generation : " + dxfobject.getType()); - } - } - // Set the visual properties for the path - path.strokeColor = new paper.Color("#ff7606"); - path.strokeWidth = 200; - // Since this is an outline we need to do the required transformations to it - path.scale(1, -1); // The coordinate system is all different for DXF - // console.log(path.bounds.topLeft); - const topleft = path.bounds.topLeft; - path.translate(new paper.Point(-topleft.x, -topleft.y)); - - // Add the feature id to the rendered object or else the whole things breaks down - // TODO: Streamline the feature ID insertion for each rendered object business - - // eslint-disable-next-line - let modpath = path as any; - modpath.featureID = feature.ID; - return modpath as paper.CompoundPath; -} - - -/** - * Generates the paper.js equivalent of the ELLIPSE DXF object - * @param entity DXF Data - * @param path Compound Path onto which the drawing will be inserted into - */ -function drawEllipse(entity: { center: { x: number; y: number; }; axisRatio: any; majorAxisEndPoint: { x: number; y: number; }; }, path: paper.CompoundPath) { - /* - https://www.autodesk.com/techpubs/autocad/acad2000/dxf/ellipse_dxf_06.htm - */ - // console.log("DXF Data", entity); - - const center = new paper.Point(entity.center.x * 1000, entity.center.y * 1000); - const axisratio = entity.axisRatio; - const majoraxislength = Math.sqrt(Math.pow(entity.majorAxisEndPoint.x * 1000, 2) + Math.pow(entity.majorAxisEndPoint.y * 1000, 2)); - const minoraxislength = majoraxislength * axisratio; - let rotation = (Math.atan(entity.majorAxisEndPoint.y / entity.majorAxisEndPoint.x) * 180) / Math.PI; - // console.log("Rotation:", rotation); - if (Number.isNaN(rotation)) { - rotation = 0; - } - // console.log("Rotation:", rotation); - // console.log("lengths:", majoraxislength, minoraxislength); - const ellipse = new paper.Path.Ellipse({ - center: [center.x, center.y], - radius: [majoraxislength, minoraxislength] - }); - - ellipse.rotate(rotation, center); - path.addChild(ellipse); -} - -function drawMtext(entity: any, data: any) { - throw new Error("Not Implemented"); - // const color = getColor(entity, data); - - // const geometry = new THREE.TextGeometry(entity.text, { - // font: font, - // size: entity.height * (4 / 5), - // height: 1 - // }); - // const material = new THREE.MeshBasicMaterial({ color: color }); - // const text = new THREE.Mesh(geometry, material); - - // // Measure what we rendered. - // const measure = new THREE.Box3(); - // measure.setFromObject(text); - - // const textWidth = measure.max.x - measure.min.x; - - // // If the text ends up being wider than the box, it's supposed - // // to be multiline. Doing that in threeJS is overkill. - // if (textWidth > entity.width) { - // console.log("Can't render this multipline MTEXT entity, sorry.", entity); - // return undefined; - // } - - // text.position.z = 0; - // switch (entity.attachmentPoint) { - // case 1: - // // Top Left - // text.position.x = entity.position.x; - // text.position.y = entity.position.y - entity.height; - // break; - // case 2: - // // Top Center - // text.position.x = entity.position.x - textWidth / 2; - // text.position.y = entity.position.y - entity.height; - // break; - // case 3: - // // Top Right - // text.position.x = entity.position.x - textWidth; - // text.position.y = entity.position.y - entity.height; - // break; - - // case 4: - // // Middle Left - // text.position.x = entity.position.x; - // text.position.y = entity.position.y - entity.height / 2; - // break; - // case 5: - // // Middle Center - // text.position.x = entity.position.x - textWidth / 2; - // text.position.y = entity.position.y - entity.height / 2; - // break; - // case 6: - // // Middle Right - // text.position.x = entity.position.x - textWidth; - // text.position.y = entity.position.y - entity.height / 2; - // break; - - // case 7: - // // Bottom Left - // text.position.x = entity.position.x; - // text.position.y = entity.position.y; - // break; - // case 8: - // // Bottom Center - // text.position.x = entity.position.x - textWidth / 2; - // text.position.y = entity.position.y; - // break; - // case 9: - // // Bottom Right - // text.position.x = entity.position.x - textWidth; - // text.position.y = entity.position.y; - // break; - - // default: - // return undefined; - // } - - // return text; -} - -function drawSpline(entity: any, path: paper.CompoundPath) { - throw new Error("Not Implemented"); - // const points = entity.controlPoints.map(function(vec) { - // return new paper.Point(vec.x, vec.y); - // }); - // let curve; - // let interpolatedPoints = []; - // if (entity.degreeOfSplineCurve === 2 || entity.degreeOfSplineCurve === 3) { - // for (let i = 0; i + 2 < points.length; i = i + 2) { - // if (entity.degreeOfSplineCurve === 2) { - // curve = new THREE.QuadraticBezierCurve(points[i], points[i + 1], points[i + 2]); - // } else { - // curve = new THREE.QuadraticBezierCurve3(points[i], points[i + 1], points[i + 2]); - // } - // interpolatedPoints.push.apply(interpolatedPoints, curve.getPoints(50)); - // } - // } else { - // curve = new THREE.SplineCurve(points); - // interpolatedPoints = curve.getPoints(400); - // } - - // const geometry = new THREE.BufferGeometry().setFromPoints(interpolatedPoints); - // const material = new THREE.LineBasicMaterial({ linewidth: 1, color: color }); - // const splineObject = new THREE.Line(geometry, material); - - // return splineObject; -} - -function drawCircle(entity: { center: { x: number; y: number; }; radius: number; }, path: paper.CompoundPath) { - const center = new paper.Point(entity.center.x * 1000, entity.center.y * 1000); - const circle = new paper.Path.Circle(center, entity.radius * 1000); - path.addChild(circle); -} - -/** - * Generates the paper.js equivalent of the LINE, POLYLINE, LWPOLYLINE DXF object - * @param entity DXF Data - * @param path Compound Path onto which the drawing will be inserted into - */ -function drawLine(entity: { vertices: string | any[]; }, path: paper.CompoundPath) { - let bulge, bugleGeometry; - let startPoint, endPoint; - - // // create geometry - for (let i = 0; i < entity.vertices.length; i++) { - if (entity.vertices[i].bulge) { - // TODO: Figure out what to do with the bugle value - bulge = entity.vertices[i].bulge; - startPoint = entity.vertices[i]; - endPoint = i + 1 < entity.vertices.length ? entity.vertices[i + 1] : entity.vertices[0]; - console.log("Start Point:", startPoint); - console.log("End Point:", endPoint); - } else { - const vertex = entity.vertices[i]; - const nextvertex = entity.vertices[i + 1 < entity.vertices.length ? i + 1 : 0]; - const point = new paper.Point(vertex.x * 1000, vertex.y * 1000); // Need to convert everything to microns - const nextpoint = new paper.Point(nextvertex.x * 1000, nextvertex.y * 1000); - // console.log("Vertex:", point, nextpoint); - const line = new paper.Path.Line(point, nextpoint); - path.addChild(line); - } - } -} - -/** - * Generates the paper.js equivalent of the ARC DXF object - * @param entity DXF Data - * @param path Compound Path onto which the drawing will be inserted into - */ -function drawArc(entity: { center: { x: number; y: number; }; radius: number; startAngle: any; endAngle: any; }, path: paper.CompoundPath) { - /* - Ok so for this to work in paperjs, we need to have 3 variables - 1. Start - 2. Through - 3. End - - DXF gives : - 1. startAngle - 2. endAngle - 3. center - 4. radius - - To translate we start with the center point, then calculate points at start angle and end angle - - center-> @------r------* <- startAngle - \ - \ - r - \ - \ - * <- endAngle - - */ - - const center = new paper.Point(entity.center.x * 1000, entity.center.y * 1000); - const radius = entity.radius * 1000; - const startAngle = entity.startAngle; - const endAngle = entity.endAngle; //* 180/Math.PI; - const midAngle = (startAngle + endAngle) / 2; - - const startpoint = new paper.Point(center.x + radius * Math.cos(startAngle), center.y + radius * Math.sin(startAngle)); - - // var starcenter = new paper.Point(startpoint); - // var points = 5; - // var radius1 = 250; - // var radius2 = 400; - // var star = new paper.Path.Star(starcenter, points, radius1, radius2); - // - // path.addChild(star); - - const midpoint = new paper.Point(center.x + radius * Math.cos(midAngle), center.y + radius * Math.sin(midAngle)); - - // starcenter = new paper.Point(midpoint); - // points = 10; - // star = new paper.Path.Star(starcenter, points, radius1, radius2); - // - // path.addChild(star); - - const endpoint = new paper.Point(center.x + radius * Math.cos(endAngle), center.y + radius * Math.sin(endAngle)); - - // starcenter = new paper.Point(endpoint); - // points = 20; - // star = new paper.Path.Star(starcenter, points, radius1, radius2); - // - // path.addChild(star); - - const arc = new paper.Path.Arc(startpoint, midpoint, endpoint); - - path.addChild(arc); -} - -function drawSolid(entity: any, data: any) { - throw new Error("Not Implemented"); - // let material; - // let mesh; - // let verts; - // const geometry = new THREE.Geometry(); - - // verts = geometry.vertices; - // verts.push(new THREE.Vector3(entity.points[0].x, entity.points[0].y, entity.points[0].z)); - // verts.push(new THREE.Vector3(entity.points[1].x, entity.points[1].y, entity.points[1].z)); - // verts.push(new THREE.Vector3(entity.points[2].x, entity.points[2].y, entity.points[2].z)); - // verts.push(new THREE.Vector3(entity.points[3].x, entity.points[3].y, entity.points[3].z)); - - // // Calculate which direction the points are facing (clockwise or counter-clockwise) - // const vector1 = new THREE.Vector3(); - // const vector2 = new THREE.Vector3(); - // vector1.subVectors(verts[1], verts[0]); - // vector2.subVectors(verts[2], verts[0]); - // vector1.cross(vector2); - - // // If z < 0 then we must draw these in reverse order - // if (vector1.z < 0) { - // geometry.faces.push(new THREE.Face3(2, 1, 0)); - // geometry.faces.push(new THREE.Face3(2, 3, 1)); - // } else { - // geometry.faces.push(new THREE.Face3(0, 1, 2)); - // geometry.faces.push(new THREE.Face3(1, 3, 2)); - // } - - // material = new THREE.MeshBasicMaterial({ color: getColor(entity, data) }); - - // return new THREE.Mesh(geometry, material); -} - -function drawText(entity: any, data: any) { - throw new Error("Not implemented yet"); - // let geometry, material, text; - - // if (!font) { - // return console.warn( - // "Text is not supported without a Three.js font loaded with THREE.FontLoader! Load a font of your choice and pass this into the constructor. See the sample for this repository or Three.js examples at http://threejs.org/examples/?q=text#webgl_geometry_text for more details." - // ); - // } - - // geometry = new THREE.TextGeometry(entity.text, { - // font: font, - // height: 0, - // size: entity.textHeight || 12 - // }); - - // material = new THREE.MeshBasicMaterial({ color: getColor(entity, data) }); - - // text = new THREE.Mesh(geometry, material); - // text.position.x = entity.startPoint.x; - // text.position.y = entity.startPoint.y; - // text.position.z = entity.startPoint.z; - - // return text; -} - -// function drawPoint(entity, data) { -// let geometry, material, point; - -// geometry = new THREE.Geometry(); - -// geometry.vertices.push(new THREE.Vector3(entity.position.x, entity.position.y, entity.position.z)); - -// // TODO: could be more efficient. PointCloud per layer? - -// const numPoints = 1; - -// const color = getColor(entity, data); -// const colors = new Float32Array(numPoints * 3); -// colors[0] = color.r; -// colors[1] = color.g; -// colors[2] = color.b; - -// geometry.colors = colors; -// geometry.computeBoundingBox(); - -// material = new THREE.PointsMaterial({ -// size: 0.05, -// vertexColors: THREE.VertexColors -// }); -// point = new THREE.Points(geometry, material); -// scene.add(point); -// } diff --git a/src/app/view/render2D/dxfSolidObjectRenderer2D.ts b/src/app/view/render2D/dxfSolidObjectRenderer2D.ts deleted file mode 100644 index f77e3dc5..00000000 --- a/src/app/view/render2D/dxfSolidObjectRenderer2D.ts +++ /dev/null @@ -1,626 +0,0 @@ -import paper from "paper"; -import * as THREE from "three"; -import LinkedList from "../../utils/linkedList"; -import GeometryGraph from "../../geometry/geometryGraph"; -import Feature from "@/app/core/feature"; -import DXFObject from "@/app/core/dxfObject"; -import CustomComponent from "@/app/core/customComponent"; - -export function renderCustomComponentFeature(feature: Feature, color: string) { - const position = feature.getValue("position"); - const rotation = feature.getValue("rotation"); - const render = renderDXFObjects(feature.dxfObjects); - render.translate(new paper.Point(position[0], position[1])); - render.rotate(rotation); - render.fillColor = new paper.Color(color); - return render; -} - -export function renderCustomComponentTarget(customcomponent: CustomComponent, params: {[key: string]: any}) { - // console.log("Render Posiition:", position); - const position = params.position; - const color = new paper.Color(params.color); - const rotation = params.rotation; - const p = new paper.Point(position[0], position[1]); - const render = renderDXFObjects(customcomponent.dxfData); - - render.fillColor = color; - render.fillColor.alpha = 0.5; - render.translate(p); - render.rotate(rotation); - return render; -} - -export function renderFeatureObjects(feature: Feature) { - console.log("rendering the features dxf objects"); - for (const i in feature.getDXFObjects()) { - const dxfobject = feature.getDXFObjects()[i]; - } - throw new Error("Implement the renderer"); -} - -/** - * Calculates and returns the bulge through point - * @param startpoint - * @param endpoint - * @param bulgevalue - * @return {paper.Point} - */ -function calculateBulgeThroughPoint(startpoint: paper.Point, endpoint: paper.Point, bulgevalue: number) { - - const start = new paper.Point(startpoint.x, startpoint.y); - const end = new paper.Point(endpoint.x, endpoint.y); - const angle = 4 * Math.atan(bulgevalue); - - /* - https://math.stackexchange.com/questions/9365/endpoint-of-a-line-knowing-slope-start-and-distance - */ - const epsilon = angle / 4; - - const midpoint = new paper.Point(startpoint.x / 2 + endpoint.x / 2, startpoint.y / 2 + endpoint.y / 2); - - const p = new paper.Point(startpoint.x, startpoint.y).getDistance(midpoint) * bulgevalue; - - let slope = (endpoint.y - startpoint.y) / (endpoint.x - startpoint.x); - - const chordvector = end.subtract(start); - - // console.log("all points:", start, end, chordvector); - /* - First handle the two cases when they're nicely aligned to the axes - */ - - // console.log(chordvector, "Angle:",chordvector.angle, Math.round(chordvector.angle), "Dist from midpoint:", p); - - if (Math.round(chordvector.angle) === 0) { - // Horizontal - // console.log("Horizontal Case"); - let throughpoint = new paper.Point(midpoint.x, midpoint.y - p); - return throughpoint; - } else if (Math.round(chordvector.angle) === 90) { - // Vertical - // console.log("Vertical Case"); - let throughpoint = new paper.Point(midpoint.x + p, midpoint.y); - return throughpoint; - } else { - // All other angles - // console.log("Angled Case") - slope = -1 * slope; - - // midpoint - const k = -p / Math.sqrt(1 + slope * slope); - - let throughpoint = midpoint.add(new paper.Point(k, k * slope)); - return throughpoint; - } - -} - -function isClosedPolyline(dxfobject: DXFObject) { - const data = dxfobject.getData(); - // console.log(data, data.shape); - return data.shape; -} - -function processARC(geometryGraph: GeometryGraph, data: {[key: string]: any}) { - // console.warn("Implement this function !!"); - - /* - - DXF gives : - 1. startAngle - 2. endAngle - 3. center - 4. radius - - To translate we start with the center point, then calculate points at start angle and end angle - - center-> @------r------* <- startAngle - \ - \ - r - \ - \ - * <- endAngle - - */ - - const center = new paper.Point(data.center.x * 1000, data.center.y * 1000); - const radius = data.radius * 1000; - const startAngle = data.startAngle; - const endAngle = data.endAngle; //* 180/Math.PI; - - const startpoint = new paper.Point(center.x + radius * Math.cos(startAngle), center.y + radius * Math.sin(startAngle)); - - const endpoint = new paper.Point(center.x + radius * Math.cos(endAngle), center.y + radius * Math.sin(endAngle)); - - geometryGraph.addEdge(startpoint, endpoint, data); -} - -function processClosedPolyLine(entity: any) { - const polygon = new paper.Path(); - - // // create geometry - for (let i = 0; i < entity.vertices.length; i++) { - const dxfvertex = entity.vertices[i]; - polygon.add(new paper.Point(dxfvertex.x * 1000, dxfvertex.y * 1000)); - } - polygon.closed = true; - - let modpath = polygon as any; - modpath.origin = "POLYLINE"; - return modpath as paper.PathItem; -} - -function processPolyLine(geometryGraph: GeometryGraph, data: any) { - console.warn("Implement this function !!"); -} - -function processSpline(geometryGraph: GeometryGraph, data: any) { - console.warn("Implement this function !!"); -} - -function processLine(geometryGraph: GeometryGraph, data: any) { - const startPoint = data.vertices[0]; - const endPoint = data.vertices[1]; - - geometryGraph.addEdge(startPoint, endPoint, data); -} - -export function renderDXFObjects(dxfobjectarray: Array) { - // let path = new paper.CompoundPath(); - - if (dxfobjectarray === undefined) { - throw new Error("Cannot find DXF DATA"); - } - // console.log("DXF Object Array to render:", dxfobjectarray); - - const patharray = new LinkedList(); - const closedshapes = []; - - const geometryGraph = new GeometryGraph(); - - for (const i in dxfobjectarray) { - const dxfobject = dxfobjectarray[i]; - - /* - If ARC - Get the start and end points - save to edge graph as - */ - - if (dxfobject.getType() === "ARC") { - processARC(geometryGraph, dxfobject.getData()); - } else if (dxfobject.getType() === "LINE") { - processLine(geometryGraph, dxfobject.getData()); - } else if (dxfobject.getType() === "LWPOLYLINE" || dxfobject.getType() === "POLYLINE") { - if (isClosedPolyline(dxfobject)) { - closedshapes.push(processClosedPolyLine(dxfobject.getData())); - } else { - processPolyLine(geometryGraph, dxfobject.getData()); - } - } else if (dxfobject.getType() === "ELLIPSE") { - closedshapes.push(drawEllipse(dxfobject.getData())); - } else if (dxfobject.getType() === "CIRCLE") { - closedshapes.push(drawCircle(dxfobject.getData())); - } else if (dxfobject.getType() === "SPLINE") { - alert("The current version of the DXF Parser does not support SPLINE objects. Support will be added in future versions"); - throw new Error("Unsupported DXF render object - SPLINE"); - // processSpline(geometryGraph, dxfobject.getData()); - } else if (dxfobject.getType() === "DIMENSION") { - console.warn("DIMENSION entry in DXF will be ignored. Please ensure that all the designs are of the correct dimensions"); - } else if (dxfobject.getType() === "MTEXT") { - console.warn("MTEXT entry in DXF will be ignored. Please ensure that none of the features require text "); - } else if (dxfobject.getType() === "INSERT") { - alert("The current version of the DXF Parser does not support INSERT and BLOCK design references."); - throw new Error("Unsupported render object"); - } else { - alert("Unsupported DXF Entity Type for Component Import : " + dxfobject.getType()); - console.error("Unsupported DXF Entity Type for Component Import : " + dxfobject.getType()); - } - } - - // console.log("Geometry grpah:",geometryGraph); - // console.log("Closed Shapes:", closedshapes); - // TODO: Generate the Geometry from the geometry graph , this should a return a compound path that takes care of the - // right kind of correct connected paths - - const path = geometryGraph.generateGeometry(); - - // TODO: Now add all the remainder closed shapes to the compound paths - for (const child of closedshapes) { - path.addChild(child); - } - - // path.strokeColor = '#000000'; - // path.strokeWidth = 1; - path.closed = true; - path.fillColor = new paper.Color("#ff7606"); - path.fillRule = "evenodd"; - const topleft = path.bounds.topLeft; - path.translate(new paper.Point(-topleft.x, -topleft.y)); - path.scale(1, -1); // The coordinate system is all different for DXF - - path.scale(1000, 1000); // Scale the coordinates to microns - - return path; -} - -/** - * Returns a PaperJS outline rendering of the given - * DXF objects contained in the feature. - * @param feature - */ -export function renderEdgeFeature(feature: Feature) { - const path = new paper.CompoundPath(""); - - // console.log('rendering the outline dxf objects....', feature.getDXFObjects()); - for (const i in feature.getDXFObjects()) { - const dxfobject = feature.getDXFObjects()[i]; - // Figure out what entity this is and then based on that do the drawing - let mesh; - if (dxfobject.getType() === "ARC") { - path.addChild(drawArc(dxfobject.getData())); - } else if (dxfobject.getType() === "LWPOLYLINE" || dxfobject.getType() === "LINE" || dxfobject.getType() === "POLYLINE") { - path.addChild(drawLine(dxfobject.getData())); - } else if (dxfobject.getType() === "SPLINE") { - path.addChild(drawSpline(dxfobject.getData(), path)); - } else if (dxfobject.getType() === "ELLIPSE") { - path.addChild(drawEllipse(dxfobject.getData())); - } else if (dxfobject.getType() === "CIRCLE") { - path.addChild(drawCircle(dxfobject.getData())); - } else { - console.error("Unsupported DXF Entity Type for Outline Generation : " + dxfobject.getType()); - } - } - // Set the visual properties for the path - path.strokeColor = new paper.Color("#ff7606"); - path.strokeWidth = 200; - // Since this is an outline we need to do the required transformations to it - path.scale(1, -1); // The coordinate system is all different for DXF - // console.log(path.bounds.topLeft); - const topleft = path.bounds.topLeft; - path.translate(new paper.Point(-topleft.x, -topleft.y)); - - // Add the feature id to the rendered object or else the whole things breaks down - // TODO: Streamline the feature ID insertion for each rendered object business - let modpath = path as any; - modpath.featureID = feature.ID; - return modpath as paper.PathItem; -} - - -/** - * Generates the paper.js equivalent of the ELLIPSE DXF object - * @param entity DXF Data - */ -function drawEllipse(entity: any) { - /* - https://www.autodesk.com/techpubs/autocad/acad2000/dxf/ellipse_dxf_06.htm - */ - // console.log("DXF Data", entity); - - const center = new paper.Point(entity.center.x * 1000, entity.center.y * 1000); - const axisratio = entity.axisRatio; - const majoraxislength = Math.sqrt(Math.pow(entity.majorAxisEndPoint.x * 1000, 2) + Math.pow(entity.majorAxisEndPoint.y * 1000, 2)); - const minoraxislength = majoraxislength * axisratio; - let rotation = (Math.atan(entity.majorAxisEndPoint.y / entity.majorAxisEndPoint.x) * 180) / Math.PI; - // console.log("Rotation:", rotation); - if (Number.isNaN(rotation)) { - rotation = 0; - } - // console.log("Rotation:", rotation); - // console.log("lengths:", majoraxislength, minoraxislength); - const ellipse = new paper.Path.Ellipse({ - center: [center.x, center.y], - radius: [majoraxislength, minoraxislength] - }); - - ellipse.rotate(rotation, center); - return ellipse; -} - -// function drawMtext(entity, data) { -// var color = getColor(entity, data); - -// var geometry = new THREE.TextGeometry(entity.text, { -// font: font, -// size: entity.height * (4 / 5), -// height: 1 -// }); -// var material = new THREE.MeshBasicMaterial({ color: color }); -// var text = new THREE.Mesh(geometry, material); - -// // Measure what we rendered. -// var measure = new THREE.Box3(); -// measure.setFromObject(text); - -// var textWidth = measure.max.x - measure.min.x; - -// // If the text ends up being wider than the box, it's supposed -// // to be multiline. Doing that in threeJS is overkill. -// if (textWidth > entity.width) { -// console.log("Can't render this multipline MTEXT entity, sorry.", entity); -// return undefined; -// } - -// text.position.z = 0; -// switch (entity.attachmentPoint) { -// case 1: -// // Top Left -// text.position.x = entity.position.x; -// text.position.y = entity.position.y - entity.height; -// break; -// case 2: -// // Top Center -// text.position.x = entity.position.x - textWidth / 2; -// text.position.y = entity.position.y - entity.height; -// break; -// case 3: -// // Top Right -// text.position.x = entity.position.x - textWidth; -// text.position.y = entity.position.y - entity.height; -// break; - -// case 4: -// // Middle Left -// text.position.x = entity.position.x; -// text.position.y = entity.position.y - entity.height / 2; -// break; -// case 5: -// // Middle Center -// text.position.x = entity.position.x - textWidth / 2; -// text.position.y = entity.position.y - entity.height / 2; -// break; -// case 6: -// // Middle Right -// text.position.x = entity.position.x - textWidth; -// text.position.y = entity.position.y - entity.height / 2; -// break; - -// case 7: -// // Bottom Left -// text.position.x = entity.position.x; -// text.position.y = entity.position.y; -// break; -// case 8: -// // Bottom Center -// text.position.x = entity.position.x - textWidth / 2; -// text.position.y = entity.position.y; -// break; -// case 9: -// // Bottom Right -// text.position.x = entity.position.x - textWidth; -// text.position.y = entity.position.y; -// break; - -// default: -// return undefined; -// } - -// return text; -// } - -function drawSpline(entity: any, path: any): paper.PathItem { - let curve; - // const points = entity.controlPoints.map(function(vec) { - // return new paper.Point(vec.x, vec.y); - // }); - throw new Error("Spline entity is not supported !"); - // let color = "black"; - // var interpolatedPoints = []; - // if (entity.degreeOfSplineCurve === 2 || entity.degreeOfSplineCurve === 3) { - // for (var i = 0; i + 2 < points.length; i = i + 2) { - // if (entity.degreeOfSplineCurve === 2) { - // curve = new THREE.QuadraticBezierCurve(points[i], points[i + 1], points[i + 2]); - // } else { - // curve = new THREE.QuadraticBezierCurve3(points[i], points[i + 1], points[i + 2]); - // } - // interpolatedPoints.push.apply(interpolatedPoints, curve.getPoints(50)); - // } - // } else { - // curve = new THREE.SplineCurve(points); - // interpolatedPoints = curve.getPoints(400); - // } - - // var geometry = new THREE.BufferGeometry().setFromPoints(interpolatedPoints); - // var material = new THREE.LineBasicMaterial({ linewidth: 1, color: color }); - // var splineObject = new THREE.Line(geometry, material); - - // return splineObject; -} - -function drawCircle(entity: any) { - const center = new paper.Point(entity.center.x * 1000, entity.center.y * 1000); - const circle = new paper.Path.Circle(center, entity.radius * 1000); - return circle; -} - -/** - * Generates the paper.js equivalent of the LINE, POLYLINE, LWPOLYLINE DXF object - * @param entity DXF Data - */ -function drawLine(entity: any) { - // Create a path - const basepath = new paper.Path(); - - let bulge, bugleGeometry; - let startPoint, endPoint; - - // // create geometry - for (let i = 0; i < entity.vertices.length; i++) { - // console.log("Point:", i , entity.vertices[i]); - if (entity.vertices[i].bulge) { - console.log("Drawing arc segment to incorporate bulge values"); - // TODO: Figure out what to do with the bugle value - bulge = entity.vertices[i].bulge; - startPoint = entity.vertices[i]; - if (i < entity.vertices.length - 1) { - endPoint = entity.vertices[i + 1]; - } else { - console.log("LAst vertex"); - endPoint = entity.vertices[0]; - } - // endPoint = (i + 1 < entity.vertices.length) ? entity.vertices[i + 1] :entity.vertices[0]; - console.log("Start Point:", startPoint); - console.log("End Point:", endPoint); - const throughpoint = calculateBulgeThroughPoint(startPoint, endPoint, bulge); - - console.log("Throughpoint:", throughpoint); - - basepath.add(new paper.Point(startPoint.x * 1000, startPoint.y * 1000)); - // basepath.add(new paper.Point(endPoint.x, endPoint.y)); - basepath.arcTo(throughpoint, new paper.Point(endPoint.x * 1000, endPoint.y * 1000)); - i++; - } else { - // let vertex = entity.vertices[i]; - // let nextvertex = entity.vertices[(i + 1 < entity.vertices.length) ? i + 1 : 0]; - // let point = new paper.Point(vertex.x * 1000, vertex.y * 1000); //Need to convert everything to microns - // let nextpoint = new paper.Point(nextvertex.x * 1000, nextvertex.y * 1000); - // // console.log("Vertex:", point, nextpoint); - // let line = new paper.Path.Line(point, nextpoint); - // path.addChild(line); - - const dxfvertex = entity.vertices[i]; - basepath.add(new paper.Point(dxfvertex.x * 1000, dxfvertex.y * 1000)); - } - } - - let modpath = basepath as any; - modpath.origin = "LINE"; - - return modpath as paper.PathItem; -} - -/** - * Generates the paper.js equivalent of the ARC DXF object - * @param entity DXF Data - */ -function drawArc(entity: any) { - /* - Ok so for this to work in paperjs, we need to have 3 variables - 1. Start - 2. Through - 3. End - - DXF gives : - 1. startAngle - 2. endAngle - 3. center - 4. radius - - To translate we start with the center point, then calculate points at start angle and end angle - - center-> @------r------* <- startAngle - \ - \ - r - \ - \ - * <- endAngle - - */ - - const center = new paper.Point(entity.center.x * 1000, entity.center.y * 1000); - const radius = entity.radius * 1000; - const startAngle = entity.startAngle; - const endAngle = entity.endAngle; //* 180/Math.PI; - const midAngle = (startAngle + endAngle) / 2; - - const startpoint = new paper.Point(center.x + radius * Math.cos(startAngle), center.y + radius * Math.sin(startAngle)); - - const midpoint = new paper.Point(center.x + radius * Math.cos(midAngle), center.y + radius * Math.sin(midAngle)); - - const endpoint = new paper.Point(center.x + radius * Math.cos(endAngle), center.y + radius * Math.sin(endAngle)); - - const arc = new paper.Path.Arc(startpoint, midpoint, endpoint); - - // arc.origin = "ARC"; - let modpath = arc as any; - modpath.origin = "ARC"; - - return modpath as paper.PathItem; -} - -// function drawSolid(entity, data) { -// var material, -// mesh, -// verts, -// geometry = new THREE.Geometry(); - -// verts = geometry.vertices; -// verts.push(new THREE.Vector3(entity.points[0].x, entity.points[0].y, entity.points[0].z)); -// verts.push(new THREE.Vector3(entity.points[1].x, entity.points[1].y, entity.points[1].z)); -// verts.push(new THREE.Vector3(entity.points[2].x, entity.points[2].y, entity.points[2].z)); -// verts.push(new THREE.Vector3(entity.points[3].x, entity.points[3].y, entity.points[3].z)); - -// // Calculate which direction the points are facing (clockwise or counter-clockwise) -// var vector1 = new THREE.Vector3(); -// var vector2 = new THREE.Vector3(); -// vector1.subVectors(verts[1], verts[0]); -// vector2.subVectors(verts[2], verts[0]); -// vector1.cross(vector2); - -// // If z < 0 then we must draw these in reverse order -// if (vector1.z < 0) { -// geometry.faces.push(new THREE.Face3(2, 1, 0)); -// geometry.faces.push(new THREE.Face3(2, 3, 1)); -// } else { -// geometry.faces.push(new THREE.Face3(0, 1, 2)); -// geometry.faces.push(new THREE.Face3(1, 3, 2)); -// } - -// material = new THREE.MeshBasicMaterial({ color: getColor(entity, data) }); - -// return new THREE.Mesh(geometry, material); -// } - -// function drawText(entity, data) { -// var geometry, material, text; - -// if (!font) -// return console.warn( -// "Text is not supported without a Three.js font loaded with THREE.FontLoader! Load a font of your choice and pass this into the constructor. See the sample for this repository or Three.js examples at http://threejs.org/examples/?q=text#webgl_geometry_text for more details." -// ); - -// geometry = new THREE.TextGeometry(entity.text, { -// font: font, -// height: 0, -// size: entity.textHeight || 12 -// }); - -// material = new THREE.MeshBasicMaterial({ color: getColor(entity, data) }); - -// text = new THREE.Mesh(geometry, material); -// text.position.x = entity.startPoint.x; -// text.position.y = entity.startPoint.y; -// text.position.z = entity.startPoint.z; - -// return text; -// } - -// function drawPoint(entity, data) { -// var geometry, material, point; - -// geometry = new THREE.Geometry(); - -// geometry.vertices.push(new THREE.Vector3(entity.position.x, entity.position.y, entity.position.z)); - -// // TODO: could be more efficient. PointCloud per layer? - -// var numPoints = 1; - -// var color = getColor(entity, data); -// var colors = new Float32Array(numPoints * 3); -// colors[0] = color.r; -// colors[1] = color.g; -// colors[2] = color.b; - -// geometry.colors = colors; -// geometry.computeBoundingBox(); - -// material = new THREE.PointsMaterial({ -// size: 0.05, -// vertexColors: THREE.VertexColors -// }); -// point = new THREE.Points(geometry, material); -// scene.add(point); -// } diff --git a/src/app/view/render2D/featureRenderer2D.ts b/src/app/view/render2D/featureRenderer2D.ts deleted file mode 100644 index b6790e4c..00000000 --- a/src/app/view/render2D/featureRenderer2D.ts +++ /dev/null @@ -1,182 +0,0 @@ -import * as DXFSolidObjectRenderer2D from "./dxfSolidObjectRenderer2D"; -import * as Colors from "../colors"; -import Registry from "../../core/registry"; -import { renderEdgeFeature } from "./dxfObjectRenderer2D"; -import paper from "paper"; -import { ComponentAPI } from "@/componentAPI"; -import {Point, ToolPaperObject} from "@/app/core/init"; -import Feature from "@/app/core/feature"; - -const getLayerColor = function(feature: Feature) { - const height = feature.getValue("height"); - const layerHeight = 1; // feature.layer.estimateLayerHeight(); - let decimal = height / layerHeight; - if (decimal > 1) decimal = 1; - // if (!feature.layer.flip) decimal = 1 - decimal; - console.log("feature Object:", feature); - console.log("feature layer:", feature.layer); - console.log("feature layer type:", feature.layer!.type); - // Throw error if the layer in the feature is null - if (!feature.layer) { - throw new Error("Feature layer is null"); - } - const targetColorSet = Colors.getLayerColors(feature.layer.type); - return Colors.decimalToLayerColor(decimal, targetColorSet, Colors.darkColorKeys); -}; - -const getBaseColor = function(feature: Feature): string { - let decimal = 0; - // if (!feature.layer.flip) decimal = 1 - decimal; - // throw error if the layer in the feature is null - if (!feature.layer) { - throw new Error("Feature layer is null"); - } - const targetColorSet = Colors.getLayerColors(feature.layer.type); - return Colors.decimalToLayerColor(decimal, targetColorSet, Colors.darkColorKeys); -}; - -export function getDefaultValueForType(typeString: string, key: string) { - return ComponentAPI.getDefaultsForType(typeString)[key]; -} - -export function renderTarget(typeString:string, position: Point, customParameters:any = null) { - if (Registry.viewManager?.currentLayer === null || Registry.viewManager?.currentLayer === undefined) { - console.error("No current layer"); - throw new Error("No current layer"); - } - const rendererinfo = ComponentAPI.getRendererInfo(typeString); - const renderer = rendererinfo.object; - const params = renderer.targetParams; - const primParams: {[key: string]: any} = {}; - if (customParameters !== null) { - for (const item of customParameters) { - primParams[item.name] = item.value; - } - } else { - for (const key in params) { - primParams[key] = getDefaultValueForType(typeString, params[key]); - } - } - primParams["position"] = position; - primParams["color"] = new paper.Color(Colors.getDefaultFeatureColor(typeString, Registry.viewManager?.currentLayer)); - const rendered = renderer.render2DTarget(null, primParams); - return rendered; -} - -/** - * This function renders the text to target that trails the cursor - * @param typeString - * @param setString - * @param position - * @return {d} - */ -export function renderTextTarget(typeString: string, position: Point) { - if (Registry.viewManager === null) { - console.error("Registry.viewManager is null"); - throw new Error("Registry.viewManager is null"); - } - const rendered = new paper.PointText(new paper.Point(position[0], position[1])); - rendered.justification = "center"; - rendered.fillColor = new paper.Color(Colors.DEEP_PURPLE_500); - rendered.content = Registry.viewManager.tools.InsertTextTool.text; - rendered.fontSize = 10000; - return rendered; -} - -export function renderEdge(feature:any) { - // TODO: Just call the DXF renderer (outline) for this - renderEdgeFeature(feature); -} - -export function renderText(feature:any) { - // TODO - Figure out where to save the position of the feature - const position = feature.getValue("position"); - const rendered = new paper.PointText(new paper.Point(position[0], position[1])); - rendered.justification = "center"; - if (feature.getParams().color != undefined) { - let color = feature.getParams().color.value; - if (color == "white" || color == "White" || color == "WHITE") { - rendered.fillColor = new paper.Color(Colors.WHITE); - } else if (color == "black" || color == "Black" || color == "BLACK") { - rendered.fillColor = new paper.Color(Colors.BLACK); - } else if (color == "blue" || color == "Blue" || color == "BLUE") { - rendered.fillColor = new paper.Color(Colors.BLUE_500); - } else if (color == "red" || color == "Red" || color == "RED") { - rendered.fillColor = new paper.Color(Colors.RED_500); - } else { - throw new Error("Color choice " + color + " not enabled"); - } - } else { - rendered.fillColor = new paper.Color(getLayerColor(feature)); - } - /// rendered.content = feature.getText(); - rendered.content = feature.getValue("text"); - rendered.fontSize = feature.getValue("fontSize"); - let modrendered = rendered as any; - modrendered["featureID"] = feature.ID; - return modrendered; -} - -/** - * Returns the paperjs drawing object of the passed feature - * @param feature - * @return {*} - */ -export function renderFeature(feature: Feature, key: string | null) { - let rendered; - let params; - const type = feature.getType(); - let set = "Basic"; - if (ComponentAPI.isCustomType(type)) { - set = "Custom"; - rendered = DXFSolidObjectRenderer2D.renderCustomComponentFeature(feature, getBaseColor(feature)); - let modrendered = rendered as any; - modrendered["featureID"] = feature.ID; - return modrendered as ToolPaperObject; - } else if (type === "EDGE") { - return renderEdge(feature); - } else if (type === "Text") { - return renderText(feature); - } else { - const rendererinfo = ComponentAPI.getRendererInfo(type); - const renderer = ComponentAPI.getRenderer(type); - - /* - If the user does not specify the key, then extract it from the rendering info of the feature. - I guess theoretically speaking, one needs to generate a set of invisible feature but for now we are just - ignoring that. - - TODO - Clean up this mess of a system. Its not obvious about how once send this logic. - */ - if (!key || key === null) { - key = rendererinfo.key; - } - - if (!renderer) { - console.error("Could not find renderer method for feature:", feature); - } else { - params = renderer.featureParams; - } - - const primParams: {[key: string]: any} = {}; - for (const paramkey in params) { - primParams[paramkey] = feature.getValue(params[paramkey]); - } - //primParams["position"] = [0,0]; - //console.log("Data for rendering:", primParams); - //Set the position of the params to 0,0 - primParams.color = getLayerColor(feature); - primParams.baseColor = getBaseColor(feature); - rendered = renderer.render2D(primParams, key); - // Rendered is going to be at 0,0 with whatever rotation - // Now we can get draw offset by looking at the rendered topleft corner - // move the feature to user pointed position - // save the drawoffsets on the feature object - // later on in the component, calculate position by subtracting draw offset - // recalculate draw offset whenever parameter changed - let modrendered = rendered as any; - modrendered["featureID"] = feature.ID; - - return modrendered as ToolPaperObject; - } -} diff --git a/src/app/view/render2D/gridRenderer.ts b/src/app/view/render2D/gridRenderer.ts deleted file mode 100644 index 9f25bbf8..00000000 --- a/src/app/view/render2D/gridRenderer.ts +++ /dev/null @@ -1,92 +0,0 @@ -import paper from "paper"; -import {SymbolDefinition} from "paper"; -import AdaptiveGrid from "../grid/adaptiveGrid"; - -export default class GridRenderer { - static renderGrid(grid: AdaptiveGrid) { - // con - const gridGroup = new paper.Group(); - gridGroup.addChild(GridRenderer.makeHorizontalLines(grid)); - gridGroup.addChild(GridRenderer.makeVerticalLines(grid)); - return gridGroup; - } - - static vertLineSymbol(width: number, color: paper.Color) { - return GridRenderer.lineSymbol(paper.view.bounds.topLeft, paper.view.bounds.bottomLeft, width, color); - } - - static horizLineSymbol(width: number, color: paper.Color) { - return GridRenderer.lineSymbol(paper.view.bounds.topLeft, paper.view.bounds.topRight, width, color); - } - - static lineSymbol(start: paper.Point, end: paper.Point, width: number, color: paper.Color) { - color.alpha = 0.25; - const line = new paper.Path.Line({ - from: start, - to: end, - strokeWidth: width, - strokeColor: color - }); - // line.strokeColor.alpha = 0.25; - line.remove(); - return new paper.SymbolDefinition(line); - } - - static isThick(val: number, origin: number, spacing:number, thickCount:number) { - const diff = Math.abs(val - origin); - const remainder = diff % (spacing * thickCount); - if (remainder < spacing) { - return true; - } else return false; - } - - static makeVerticalLines(grid: AdaptiveGrid) { - const spacing = grid.getSpacing(); - const sym = GridRenderer.vertLineSymbol(grid.getThinWidth(), grid.color); - const thickSym = GridRenderer.vertLineSymbol(grid.getThickWidth(), grid.color); - const start = paper.view.bounds.topLeft; - const end = paper.view.bounds.topRight; - const height = paper.view.bounds.height; - const group = new paper.Group(); - - const startX = Math.floor((start.x - grid.origin.x) / spacing) * spacing + grid.origin.x; - - for (let i = startX; i < end.x; i += spacing) { - const pos = new paper.Point(i, start.y + height / 2); - if (GridRenderer.isThick(i, grid.origin.x, spacing, grid.thickCount)) group.addChild(thickSym.place(pos)); - else group.addChild(sym.place(pos)); - } - - for (let i = startX; i >= end.x; i -= spacing) { - const pos = new paper.Point(i, start.y + height / 2); - if (GridRenderer.isThick(i, grid.origin.x, spacing, grid.thickCount)) group.addChild(thickSym.place(pos)); - else group.addChild(sym.place(pos)); - } - return group; - } - - static makeHorizontalLines(grid: AdaptiveGrid) { - const spacing = grid.getSpacing(); - const sym = GridRenderer.horizLineSymbol(grid.getThinWidth(), grid.color); - const thickSym = GridRenderer.horizLineSymbol(grid.getThickWidth(), grid.color); - const start = paper.view.bounds.topLeft; - const end = paper.view.bounds.bottomLeft; - const width = paper.view.bounds.width; - const group = new paper.Group(); - - const startY = Math.floor((start.y - grid.origin.y) / spacing) * spacing + grid.origin.y; - - for (let i = startY; i < end.y; i += spacing) { - const pos = new paper.Point(start.x + width / 2, i); - if (GridRenderer.isThick(i, grid.origin.y, spacing, grid.thickCount)) group.addChild(thickSym.place(pos)); - else group.addChild(sym.place(pos)); - } - - for (let i = startY; i >= end.y; i -= spacing) { - const pos = new paper.Point(start.x + width / 2, i); - if (GridRenderer.isThick(i, grid.origin.y, spacing, grid.thickCount)) group.addChild(thickSym.place(pos)); - else group.addChild(sym.place(pos)); - } - return group; - } -} diff --git a/src/app/view/render2D/paperComponentPortView.ts b/src/app/view/render2D/paperComponentPortView.ts deleted file mode 100644 index 6daa2acf..00000000 --- a/src/app/view/render2D/paperComponentPortView.ts +++ /dev/null @@ -1,90 +0,0 @@ -import Component from "@/app/core/component"; -import { Point } from "paper/dist/paper-core"; -import ViewManager from "../viewManager"; -import ComponentPortRenderer2D from "./componentPortRenderer2D"; - -export default class PaperComponentPortView { - - private _viewManagerDelegate: ViewManager; - private _componentAndRenderMap: Map>; - private _activeRenders: Array; - private _paperlayer: paper.Group; - private _enabled: boolean; - - constructor(paperlayer: paper.Group, viewmanager: ViewManager) { - this._paperlayer = paperlayer; - this._componentAndRenderMap = new Map(); - this._activeRenders = []; - this._viewManagerDelegate = viewmanager; - this._enabled = true; - } - - addComponentPortElements(component: Component) { - const zfactor = 1; - if (!this._componentAndRenderMap.has(component.id)) { - this._componentAndRenderMap.set(component.id, []); - } - - const componentportrenders = this._componentAndRenderMap.get(component.id); - - if (componentportrenders === undefined) { - console.error(`component ${component.id} has no port renders`); - return; - } - - for (const key of component.ports.keys()) { - const componentport = component.ports.get(key); - if (componentport === undefined) { - console.error(`component ${component.id} has no port ${key}`); - continue; - } - // TODO - Fix this API - const render = ComponentPortRenderer2D.renderComponentPort(componentport, [0,0], 0, zfactor); - componentportrenders.push(render); - } - } - - updateRenders() { - if(this._viewManagerDelegate.currentDevice === null){ - console.error("No device selected, not rendering component ports"); - return; - } - - if (!this._enabled) { - this.clearActiveRenders(); - return; - } - this.clearActiveRenders(); - const components = this._viewManagerDelegate.currentDevice.components; - for (const i in components) { - const component = components[i]; - const renders = ComponentPortRenderer2D.renderComponentPorts(component); - for (const j in renders) { - this._activeRenders.push(renders[j]); - this._paperlayer.addChild(renders[j]); - } - } - } - - clearActiveRenders() { - if (!this._enabled) { - return; - } - if (this._activeRenders) { - for (const i in this._activeRenders) { - this._activeRenders[i].remove(); - } - } - - this._activeRenders = []; - } - - enable() { - this._enabled = true; - } - - disable() { - this.clearActiveRenders(); - this._enabled = false; - } -} diff --git a/src/app/view/render2D/ratsNestRenderer2D.ts b/src/app/view/render2D/ratsNestRenderer2D.ts deleted file mode 100644 index 58777df1..00000000 --- a/src/app/view/render2D/ratsNestRenderer2D.ts +++ /dev/null @@ -1,47 +0,0 @@ -import Connection from "@/app/core/connection"; -import { Point } from "@/app/core/init"; -import paper from "paper"; -import Device from "@/app/core/device"; - -export default class RatsNestRenderer2D { - static renderRatsNest(connectionlist: Array, device: Device) { - const ratsnestgroup = new paper.Group(); - let start, end, sink, render, sourceid, sinkid; - for (const i in connectionlist) { - const connection = connectionlist[i]; - const source = connection.source; - if (source === null) { - console.error(`source ${connection.id} is null, cannot render rats nest`); - continue; - } - const sinks = connection.sinks; - // console.log("Sinks", sinks, sinks.length); - for (const ii in sinks) { - sink = sinks[ii]; - const startcomponent = source.component; - const endcomponent = sink.component; - start = startcomponent.getCenterPosition(); - end = endcomponent.getCenterPosition(); - // console.log(start, end); - render = RatsNestRenderer2D.renderRatsNestConnection(start, end); - ratsnestgroup.addChild(render); - } - } - - return ratsnestgroup; - } - - static renderRatsNestConnection(start: Point, end: Point) { - const vstart = new paper.Point(start[0], start[1]); - const vend = new paper.Point(end[0], end[1]); - - const vpath = new paper.Path([vstart, vend]); - - vpath.strokeColor = new paper.Color("#696965"); - vpath.strokeWidth = 500; - vpath.strokeCap = "round"; - - vpath.dashArray = [1000, 1300]; - return vpath; - } -} diff --git a/src/app/view/renderLayer.ts b/src/app/view/renderLayer.ts deleted file mode 100644 index e0188a6d..00000000 --- a/src/app/view/renderLayer.ts +++ /dev/null @@ -1,351 +0,0 @@ -import uuid from "node-uuid"; -import Feature from "../core/feature"; -import EdgeFeature from "../core/edgeFeature"; - -import { RenderLayerInterchangeV1_2, FeatureInterchangeV1_2, LayerInterchangeV1, LogicalLayerType } from "../core/init"; -import Layer from "../core/layer"; -import Params from "../core/params"; -import { ComponentAPI } from "@/componentAPI"; - -export default class RenderLayer { - features: { [index: string]: Feature }; - featureCount: number; - color: string | undefined; - private __id: string; - private __type: LogicalLayerType; - name: string; - protected _physicalLayer: Layer | null; - protected params: Params; - - constructor(name: string = "New Layer", modellayer: Layer | null = null, type: LogicalLayerType = LogicalLayerType.FLOW) { - this.__type = type; - this.features = {}; - this.featureCount = 0; - this.name = name; - if (modellayer) this.params = modellayer.params; - else this.params = new Params([], Layer.getUniqueParameters(), new Map()); - this._physicalLayer = modellayer; - if (type == LogicalLayerType.FLOW) { - this.color = "indigo"; - } else if (type == LogicalLayerType.CONTROL) { - this.color = "red"; - } else if (type == LogicalLayerType.INTEGRATION) { - this.color = "green"; - } else { - this.color = undefined; - } - this.__id = ComponentAPI.generateID(); - } - - /** - * Sets the render layer - * - * @memberof RenderLayer - */ - set physicalLayer(layer: Layer | null) { - this._physicalLayer = layer; - } - - /** - * returns the render layer - * - * @type {(Layer | null)} - * @memberof RenderLayer - */ - get physicalLayer(): Layer | null { - return this._physicalLayer; - } - - /** - * Returns the type of the render layer - * - * @readonly - * @type {string} - * @memberof RenderLayer - */ - get type(): LogicalLayerType { - return this.__type; - } - - /** - * Returns id of the render layer - * - * @readonly - * @type {string} - * @memberof RenderLayer - */ - get id(): string { - return this.__id; - } - - /** - * Adds a feature to the layer - * @param {Feature} feature Feature to pass to add to the layer - * @memberof Layer - * @returns {void} - */ - addFeature(feature: Feature, physfeat: boolean = true): void { - this.__ensureIsAFeature(feature); - this.features[feature.ID] = feature; - this.featureCount += 1; - if (this.physicalLayer !== null && physfeat == true) { - this.physicalLayer.addFeature(feature); - feature.layer = this.physicalLayer; - } else { - feature.layer = this.physicalLayer; - } - feature.setManufacturingInfoLayer(); - } - - /** - * Checks whether the argument pass is a feature - * @param {Feature} feature Feature object - * @memberof Layer - * @returns {void} - */ - __ensureIsAFeature(feature: any): void { - if (!(feature instanceof Feature) && !(feature instanceof EdgeFeature)) { - throw new Error("Provided value" + feature + " is not a Feature! Did you pass an ID by mistake?"); - } - } - - /** - * Checks whether the feature already exist - * @param {Feature} feature Feature object - * @memberof Layer - * @returns {void} - */ - __ensureFeatureExists(feature: Feature): void { - if (!this.containsFeature(feature)) throw new Error("Layer does not contain the specified feature!"); - } - - /** - * Checks if feature exist based on it's ID - * @param {String} featureID ID of the feature to search for - * @memberof Layer - * @returns {void} - */ - __ensureFeatureIDExists(featureID: string): void { - if (!this.containsFeatureID(featureID)) throw new Error("Layer does not contain a feature with the specified ID!"); - } - - /** - * Returns feature based on it's ID - * @param {String} featureID - * @returns {Feature} - * @memberof Layer - */ - getFeature(featureID: string): Feature { - this.__ensureFeatureIDExists(featureID); - return this.features[featureID]; - } - - /** - * Removes selected feature - * @param {Feature} feature Feature object - * @memberof Layer - * @returns {void} - */ - removeFeature(feature: Feature): void { - this.removeFeatureByID(feature.ID); - } - - // TODO: Stop using delete, it's slow! - /** - * Removes a feature by passing it's ID as a parameter - * @param {string} featureID ID of the feature - * @memberof Layer - * @returns {void} - */ - removeFeatureByID(featureID: string): void { - this.__ensureFeatureIDExists(featureID); - this.featureCount -= 1; - let physLayer = this._physicalLayer; - if (physLayer !== null) { - if (physLayer.containsFeatureID(featureID)) physLayer.removeFeatureByID(featureID); - } - delete this.features[featureID]; - } - - /** - * Checks if object contains a feature - * @param {Feature} feature Feature object - * @returns {Boolean} true if it has the feature - * @memberof Layer - */ - containsFeature(feature: Feature): boolean { - this.__ensureIsAFeature(feature); - return this.features.hasOwnProperty(feature.ID); - } - - /** - * Checks if object contains a feature based on the feature's ID - * @param {String} featureID ID of the feature to search for - * @returns {Boolean} true if it has the feature - * @memberof Layer - */ - containsFeatureID(featureID: string): boolean { - return this.features.hasOwnProperty(featureID); - } - - /** - * Gets all features from the layers - * @returns {Array} Returns all features from the layers - * @memberof Layer - */ - getAllFeaturesFromLayer(): { [index: string]: Feature } { - return this.features; - } - - /** - * Convers features to JSON format - * @returns {JSON} Returns a JSON format with the features in a JSON format - * @memberof Layer - */ - __featuresToJSON(): { [index: string]: any } { - const output: { [index: string]: any } = {}; - for (const i in this.features) { - output[i] = this.features[i].toJSON(); - } - return output; - } - - /** - * Converts features to Interchange format - * @returns {Array} Returns an array with the features in Interchange format - * @memberof Layer - */ - __featuresInterchangeV1(): Array { - const output: Array = []; - for (const i in this.features) { - output.push(this.features[i].toInterchangeV1()); - } - return output; - } - - /** - * Loads features from JSON format - * @param {JSON} json JSON format file - * @memberof Layer - */ - __loadFeaturesFromJSON(json: { [index: string]: any }): void { - for (const i in json) { - this.addFeature(Feature.fromJSON(json[i])); - } - } - - /** - * Loads features from Interchange format - * @param {FeatureInterchangeV1_2} json Interchange format file - * @memberof RenderLayer - */ - __loadFeaturesFromInterchangeV1(json: Array): void { - for (const i in json) { - this.addFeature(Feature.fromInterchangeV1(json[i])); - } - } - - /** - * Converts the model layer into Interchange format - * @returns {LayerInterchangeV1 | null} Returns a Interchange format with the attributes of the object - * @memberof RenderLayer - */ - __layerToInterchangeV1(): LayerInterchangeV1 | null { - if (this._physicalLayer !== null) { - return this._physicalLayer.toInterchangeV1(); - } - return null; - } - - // /** - // * Loads physical layer from json format - // * @param {json} json format file - // * @memberof RenderLayer - // */ - // __loadLayerFromJSON(json: { [index: string]: any }): void { - // this.physicalLayer = Layer.fromJSON(json); - // } - - // /** - // * Loads physical layer from Interchange format - // * @param {LayerInterchangeV1} json Interchange format file - // * @memberof RenderLayer - // */ - // __loadLayerFromInterchange(json: LayerInterchangeV1): void { - // this.physicalLayer = Layer.fromInterchangeV1(json); - // } - - /** - * Converts the attributes of the object into Interchange format - * @returns {LayerInterchangeV1} Returns a Interchange format with the attributes of the object - * @memberof Layer - */ - toInterchangeV1(): RenderLayerInterchangeV1_2 { - let physlayer; - if (this.physicalLayer) { - physlayer = this.physicalLayer.id; - } else { - physlayer = null; - } - const output: RenderLayerInterchangeV1_2 = { - id: this.__id, - name: this.name, - //name: this.name, - // TODO - Add group and unique name parameters to the system and do type checking - // against type and not name in the future - modellayer: physlayer, - type: this.__type, - //params: this.params.toJSON(), - features: this.__featuresInterchangeV1(), - color: this.color - }; - return output; - } - - /** - * Load from a JSON format a new layer object - * @param {JSON} json JSON format - * @returns {Layer} Returns a new layer object - * @memberof Layer - */ - static fromJSON(json: { [index: string]: any }): RenderLayer { - //Effectively defunct, use loadUtils version - if (!Object.prototype.hasOwnProperty.call(json, "features")) { - throw new Error("JSON layer has no features!"); - } - const newLayer = new RenderLayer(json.name, null, json.type); - newLayer.__loadFeaturesFromJSON(json.features); - //if (json.modellayer) newLayer.__loadLayerFromJSON(json.modellayer); - if (json.color) newLayer.color = json.color; - return newLayer; - } - - /** - * Load from an Interchange format a new layer object - * @param {*} json - * @returns {Layer} Returns a new layer object - * @memberof Layer - */ - static fromInterchangeV1(json: RenderLayerInterchangeV1_2): RenderLayer { - //Effectively defunct, use loadUtils version - let layerType: LogicalLayerType | undefined; - if (Object.prototype.hasOwnProperty.call(json, "type")) { - if (json.type === "FLOW") { - layerType = LogicalLayerType.FLOW; - } else if (json.type === "CONTROL") { - layerType = LogicalLayerType.CONTROL; - } else if (json.type === "INTEGRATION") { - layerType = LogicalLayerType.INTEGRATION; - } else { - throw new Error("Unknown layer type: " + json.type); - } - } - const newLayer: RenderLayer = new RenderLayer(json.name, null, layerType); - - newLayer.__loadFeaturesFromInterchangeV1(json.features); - - //if (json.modellayer) newLayer.__loadLayerFromInterchange(json.modellayer); - if (json.color) newLayer.color = json.color; // TODO: Figure out if this needs to change in the future - return newLayer; - } -} diff --git a/src/app/view/selection.ts b/src/app/view/selection.ts deleted file mode 100644 index bca4052a..00000000 --- a/src/app/view/selection.ts +++ /dev/null @@ -1,185 +0,0 @@ -import paper from "paper"; -import { ViewManager } from ".."; - -/** - * Selection class - */ -export default class Selection { - protected __components: Array; - protected __connections: Array; - protected __otherFeatures: Array; - protected __bounds: paper.Rectangle; - private viewManagerDelegate: ViewManager; - - /** - * Pass an array of feature IDs that can be used to store the selection - * @param {Array} items Array of String - */ - constructor(items: Array, viewManager: ViewManager) { - this.__components = []; - this.__connections = []; - this.__otherFeatures = []; - // Sort out wether each of the items selected belongs to one of the following - for (const i in items) { - console.log(items[i]); - } - this.__bounds = this.__calculateSelectionBounds(); - this.viewManagerDelegate = viewManager; - } - - /** - * Generates a replica - * @param {number} x X coordinate for here the selection should be replicated - * @param {number} y Y coordinate for where the selection should be replicated - * @returns {void} - * @memberof Selection - */ - replicate(x: number, y: number): void { - /* - 1. Get the selection's reference point - 2. Go through each of the items - 3. Clone components/connections/other features - */ - const referencepoint = this.__bounds.topLeft; - - console.log("reference point:", referencepoint); - - if (this.viewManagerDelegate.currentDevice === null) { - throw new Error("No device selected"); - } - for (const i in this.__components) { - const render = this.viewManagerDelegate.currentDevice.getFeatureByID(this.__components[i]); - } - - for (const i in this.__connections) { - const render = this.viewManagerDelegate.currentDevice.getFeatureByID(this.__connections[i]); - } - - for (const i in this.__otherFeatures) { - const render = this.viewManagerDelegate.currentDevice.getFeatureByID(this.__otherFeatures[i]); - } - } - - /** - * Selects all the components, connections and features - * @returns {void} - * @memberof Selection - */ - selectAll(): void { - // Check if currentDevices is null - if (this.viewManagerDelegate.currentDevice === null) { - throw new Error("No device selected"); - } - for (const i in this.__components) { - const component = this.viewManagerDelegate.currentDevice.getComponentByID(this.__components[i]); - if (component === null) { - throw new Error("Component not found"); - } - for (const j in component.featureIDs) { - const feature = this.viewManagerDelegate.currentDevice.getFeatureByID(component.featureIDs[i]); - const render = this.viewManagerDelegate.view.getRender(feature.ID); - render.selected = true; - } - } - - for (const i in this.__connections) { - const connection = this.viewManagerDelegate.currentDevice.getConnectionByID(this.__connections[i]); - if (connection === null) { - throw new Error("Connection not found"); - } - for (const j in connection.featureIDs) { - const feature = this.viewManagerDelegate.currentDevice.getFeatureByID(connection.featureIDs[i]); - const render = this.viewManagerDelegate.view.getRender(feature.ID); - render.selected = true; - } - } - - for (const i in this.__otherFeatures) { - const feature = this.viewManagerDelegate.currentDevice.getFeatureByID(this.__otherFeatures[i]); - const render = this.viewManagerDelegate.view.getRender(feature.ID); - render.selected = true; - } - } - - /** - * Gets all the bounds - * @returns {Array} Returns an array containing the bounds of the selection - * @memberof Selection - */ - get bounds(): paper.Rectangle { - return this.__bounds; - } - - /** - * Calculates how much area has been selected - * @returns {void} - * @memberof Selection - */ - __calculateSelectionBounds(): paper.Rectangle { - let xmin = 0; - let ymin = 0; - let xmax = 0; - let ymax = 0; - let bounds; - - if(this.viewManagerDelegate.currentDevice === null) { - throw new Error("No device selected"); - } - for (const i in this.__components) { - const feature = this.viewManagerDelegate.currentDevice.getFeatureByID(this.__components[i]); - const render = this.viewManagerDelegate.view.getRender(feature.ID); - bounds = render.bounds; - if (bounds.x < xmin) { - xmin = bounds.x; - } - if (bounds.y < ymin) { - ymin = bounds.y; - } - if (bounds.x + bounds.width > xmax) { - xmax = bounds.x + bounds.width; - } - if (bounds.y + bounds.height > ymax) { - ymax = bounds.y + bounds.height; - } - } - - for (const i in this.__connections) { - const feature = this.viewManagerDelegate.currentDevice.getFeatureByID(this.__connections[i]); - const render = this.viewManagerDelegate.view.getRender(feature.ID); - bounds = render.bounds; - if (bounds.x < xmin) { - xmin = bounds.x; - } - if (bounds.y < ymin) { - ymin = bounds.y; - } - if (bounds.x + bounds.width > xmax) { - xmax = bounds.x + bounds.width; - } - if (bounds.y + bounds.height > ymax) { - ymax = bounds.y + bounds.height; - } - } - - for (const i in this.__otherFeatures) { - const feature = this.viewManagerDelegate.currentDevice.getFeatureByID(this.__otherFeatures[i]); - const render = this.viewManagerDelegate.view.getRender(feature.ID); - bounds = render.bounds; - if (bounds.x < xmin) { - xmin = bounds.x; - } - if (bounds.y < ymin) { - ymin = bounds.y; - } - if (bounds.x + bounds.width > xmax) { - xmax = bounds.x + bounds.width; - } - if (bounds.y + bounds.height > ymax) { - ymax = bounds.y + bounds.height; - } - } - - const ret = new paper.Rectangle(new paper.Point(xmin, ymin), new paper.Point(xmax, ymax)); - return ret; - } -} diff --git a/src/app/view/textElement.ts b/src/app/view/textElement.ts deleted file mode 100644 index fb24c522..00000000 --- a/src/app/view/textElement.ts +++ /dev/null @@ -1,13 +0,0 @@ -import Parameter from "../core/parameter"; -import { ComponentAPI } from "@/componentAPI"; -import UIElement from "./uiElement"; - -export default class TextElement extends UIElement { - constructor(type: string, paramdata: { [index: string]: Parameter }, featureIDs: Array, id: string = ComponentAPI.generateID()) { - super(id); - this.__position = paramdata.position.value; - this.__height = paramdata.height.value; - this.__type = type; - this.__featureIDs = featureIDs; - } -} diff --git a/src/app/view/tools/cellPositionTool.ts b/src/app/view/tools/cellPositionTool.ts deleted file mode 100644 index fde9aad0..00000000 --- a/src/app/view/tools/cellPositionTool.ts +++ /dev/null @@ -1,53 +0,0 @@ -import PositionTool from "./positionTool"; -import paper from "paper"; -import Registry from "../../core/registry"; -import Device from "../../core/device"; -import ViewManager from "@/app/view/viewManager"; -import Parameter from "../../core/parameter"; -export default class CellPositionTool extends PositionTool { - constructor(viewManagerDelegate: ViewManager, typeString: string, setString: string, currentParameters = null) { - super(viewManagerDelegate, typeString, currentParameters); - } - - createNewFeature(point: paper.Point): void { - const featureIDs = []; - const currentlevel = Math.floor(Registry.viewManager!.renderLayers.indexOf(this.viewManagerDelegate.currentLayer) / 3); - const flowlayer = currentlevel * 3; - const controllayer = currentlevel * 3 + 1; - const cell_layer = currentlevel * 3; - - const paramvalues = this.getCreationParameters(new paper.Point(0, 0)); - let newFeature = Device.makeFeature(this.typeString, paramvalues); - this.currentFeatureID = newFeature.ID; - this.viewManagerDelegate.addFeature(newFeature, flowlayer); - - featureIDs.push(newFeature.ID); - - const params_to_copy = newFeature.getParams(); - - const params_point = PositionTool.getTarget([point.x, point.y]); - const newtypestring = this.typeString + "_cell"; - const paramstoadd = newFeature.getParams(); - paramstoadd["position"] = new Parameter("position", params_point); - newFeature = Device.makeFeature(newtypestring, paramvalues); - newFeature.setParams(paramstoadd); - - this.currentFeatureID = newFeature.ID; - this.viewManagerDelegate.addFeature(newFeature, cell_layer); - featureIDs.push(newFeature.ID); - - super.createNewComponent(this.typeString, params_to_copy, featureIDs); - Registry.viewManager!.saveDeviceState(); - } - - showTarget(): void { - if (this.lastPoint === null) { - return; - } - if (this.currentParameters === null) { - throw new Error("No parameters set"); - } - const target = PositionTool.getTarget(this.lastPoint); - this.viewManagerDelegate.updateTarget(this.typeString, this.setString, target, this.currentParameters); - } -} diff --git a/src/app/view/tools/channelTool.ts b/src/app/view/tools/channelTool.ts deleted file mode 100644 index 78e44838..00000000 --- a/src/app/view/tools/channelTool.ts +++ /dev/null @@ -1,141 +0,0 @@ -import MouseTool from "./mouseTool"; - -import Registry from "../../core/registry"; -import SimpleQueue from "../../utils/simpleQueue"; -import Device from "../../core/device"; -import paper from "paper"; -import { Point, ToolPaperObject } from "@/app/core/init"; -import ViewManager from "../viewManager"; - -export default class ChannelTool extends MouseTool { - typeString: string; - setString: string; - startPoint: Point | null; - lastPoint: Point | null; - currentChannelID: string | null; - currentTarget: any; - dragging: boolean; - - showQueue: SimpleQueue; - updateQueue: SimpleQueue; - - constructor(viewManager: ViewManager, typeString: string, setString: string) { - super(viewManager); - this.typeString = typeString; - this.setString = setString; - this.startPoint = null; - this.lastPoint = null; - this.currentChannelID = null; - this.currentTarget = null; - this.dragging = false; - const ref = this; - - this.showQueue = new SimpleQueue( - function() { - if(ref.lastPoint === null){ - return; - } - ref.showTarget(new paper.Point(ref.lastPoint)); - }, - 20, - false - ); - - this.updateQueue = new SimpleQueue( - function() { - ref.updateChannel(); - }, - 20, - false - ); - - this.down = function(event) { - Registry.viewManager?.killParamsWindow(); - paper.project.deselectAll(); - ref.dragging = true; - ref.initChannel(); - }; - this.up = function(event) { - ref.dragging = false; - ref.finishChannel((MouseTool.getEventPosition((event as unknown) as MouseEvent) as unknown) as Point); - }; - this.move = function(event) { - ref.lastPoint = (MouseTool.getEventPosition((event as unknown) as MouseEvent) as unknown) as Point; - if (ref.dragging) { - ref.updateQueue.run(); - } - ref.showQueue.run(); - }; - } - - static makeReticle(point: paper.Point) { - const size = 10 / paper.view.zoom; - const ret = new paper.Path.Circle(point, size); - ret.fillColor = new paper.Color(0.5, 0, 1, 0.5); - return ret; - } - - abort(): void { - this.dragging = false; - if (this.currentTarget) { - this.currentTarget.remove(); - } - if (this.currentChannelID) { - Registry.viewManager?.removeFeatureByID(this.currentChannelID); - } - } - - showTarget(point: paper.Point): void { - const target = ChannelTool.getTarget(this.lastPoint!); - Registry.viewManager?.updateTarget(this.typeString, this.setString, target, {}); - } - - initChannel(): void { - this.startPoint = ChannelTool.getTarget(this.lastPoint!); - this.lastPoint = this.startPoint; - } - - updateChannel(): void { - if (this.lastPoint && this.startPoint) { - if (this.currentChannelID) { - const target = ChannelTool.getTarget(this.lastPoint); - const feat = this.viewManagerDelegate.currentLayer.getFeature(this.currentChannelID); - feat?.updateParameter("end", target); - } else { - const newChannel = ChannelTool.createChannel(this.startPoint, this.startPoint, this.typeString, this.setString); - this.currentChannelID = newChannel.ID; - Registry.viewManager?.addFeature(newChannel); - } - } - } - - finishChannel(point: Point): void { - const target = ChannelTool.getTarget(point); - if (this.currentChannelID) { - if (this.startPoint![0] === target[0] && this.startPoint![1] === target[1]) { - Registry.viewManager?.removeFeatureByID(this.currentChannelID); - } - } else { - this.updateChannel(); - } - this.currentChannelID = null; - this.startPoint = null; - Registry.viewManager?.saveDeviceState(); - } - - static createChannel(start: any, end: any, typestring: string | null = null, setstring: string | null = null) { - return Device.makeFeature(typestring!, { - start: start, - end: end - }); - } - - // TODO: Re-establish target selection logic from earlier demo - static getTarget(point: Point): Point { - if (Registry.viewManager === null){ - throw new Error("ViewManager not initialized"); - } - const target = Registry.viewManager.snapToGrid(point); - return target; - } -} diff --git a/src/app/view/tools/componentPositionTool.ts b/src/app/view/tools/componentPositionTool.ts deleted file mode 100644 index d669d1a1..00000000 --- a/src/app/view/tools/componentPositionTool.ts +++ /dev/null @@ -1,30 +0,0 @@ -import PositionTool from "./positionTool"; -import Registry from "../../core/registry"; -import Device from "../../core/device"; -import ViewManager from "@/app/view/viewManager"; -import paper from "paper"; -import Parameter from "@/app/core/parameter"; - -export default class ComponentPositionTool extends PositionTool { - constructor(viewManagerDelegate: ViewManager, typeString: string, setString: string, currentParams: { [k: string]: any } | null = null) { - super(viewManagerDelegate, typeString, currentParams); - } - - createNewFeature(point: paper.Point): void { - const featureIDs = []; - const paramvalues = this.getCreationParameters(new paper.Point(0, 0)); - const newFeature = Device.makeFeature(this.typeString, paramvalues); - this.currentFeatureID = newFeature.ID; - - this.viewManagerDelegate.addFeature(newFeature); - - featureIDs.push(newFeature.ID); - - const params_point = PositionTool.getTarget([point.x, point.y]); - - const params_to_copy = newFeature.getParams(); - params_to_copy["position"] = new Parameter("position", params_point); - super.createNewComponent(this.typeString, params_to_copy, featureIDs); - Registry.viewManager?.saveDeviceState(); - } -} diff --git a/src/app/view/tools/connectionTool.ts b/src/app/view/tools/connectionTool.ts deleted file mode 100644 index c0034a48..00000000 --- a/src/app/view/tools/connectionTool.ts +++ /dev/null @@ -1,577 +0,0 @@ -import MouseTool from "./mouseTool"; -import Connection from "../../core/connection"; -import SimpleQueue from "../../utils/simpleQueue"; -import Device from "../../core/device"; -import paper from "paper"; -import Params from "../../core/params"; -import ConnectionTarget from "../../core/connectionTarget"; -import ComponentPort from "../../core/componentPort"; -import { ComponentAPI } from "@/componentAPI"; -import EventBus from "@/events/events"; -import { LogicalLayerType, Point, ToolPaperObject } from "@/app/core/init"; - -import Registry from "../../core/registry"; -import MapUtils from "../../utils/mapUtils"; -import PositionTool from "./positionTool"; -import { ViewManager } from "@/app"; - -export enum ConnectionToolState { - PLACE_FIRST_POINT, - TARGET_PLACED_START_AGAIN, - PLACE_WAYPOINT, - INTERSECTION_AWAITING_USER_INPUT -} - -export default class ConnectionTool extends MouseTool { - typeString: string; - setString: string; - startPoint: Point | null; - lastPoint: Point | null; - wayPoints: any[]; - currentChannelID: string | null; - currentTarget: paper.Point | null; - dragging: boolean; - source: ConnectionTarget | null; - sinks: Array; - - private __currentConnectionObject: Connection | null; - private __STATE: ConnectionToolState = ConnectionToolState.PLACE_FIRST_POINT; - showQueue: SimpleQueue; - updateQueue: SimpleQueue; - - - public get state() : ConnectionToolState { - return this.__STATE; - } - - - constructor(viewManagerDelegate: ViewManager, typeString: string, setString: string) { - super(viewManagerDelegate); - this.typeString = typeString; - this.setString = setString; - this.startPoint = null; - this.lastPoint = [0,0]; - this.wayPoints = []; - this.currentChannelID = null; - this.currentTarget = null; - this.dragging = false; - this.source = null; - this.sinks = []; - this.__currentConnectionObject = null; - - /* - States: - 1. SOURCE - 2. WAYPOINT - 3. TARGET - */ - const ref = this; - - this.showQueue = new SimpleQueue( - function () { - if (ref.lastPoint === null) { - return; - } - ref.showTarget(new paper.Point(ref.lastPoint)); - }, - 20, - false - ); - - this.updateQueue = new SimpleQueue( - function () { - ref.updateChannel(); - }, - 20, - false - ); - - this.down = function (event) { - Registry.viewManager?.killParamsWindow(); - paper.project.deselectAll(); - console.log("Current State:", ref.__STATE); - switch (ref.__STATE) { - case ConnectionToolState.PLACE_FIRST_POINT: - ref.__STATE = ConnectionToolState.PLACE_WAYPOINT; - ref.dragging = true; - ref.initChannel(); - break; - case ConnectionToolState.PLACE_WAYPOINT: - ref.addWayPoint(event as unknown as MouseEvent, (event as any).altKey); - break; - case ConnectionToolState.TARGET_PLACED_START_AGAIN: - ref.__STATE = ConnectionToolState.PLACE_WAYPOINT; - ref.dragging = true; - ref.initChannel(); - // ref.createConnection(); - break; - } - }; - - this.rightdown = function (event) { - ref.__STATE = ConnectionToolState.TARGET_PLACED_START_AGAIN; - ref.dragging = false; - const end = ref.wayPoints.pop(); - ref.lastPoint = end; - ref.finishChannel(); - EventBus.get().emit(EventBus.RIGHT_CLICK); - }; - - this.move = function (event) { - // Check if orthogonal - const point = MouseTool.getEventPosition(event as unknown as MouseEvent); - if (point === null) return; - const target = PositionTool.getTarget([point.x, point.y]); - - if ((event as any).altKey && ref.__STATE === ConnectionToolState.PLACE_WAYPOINT) { - let lastwaypoint = ref.startPoint; - if (ref.wayPoints.length > 0) { - lastwaypoint = ref.wayPoints[ref.wayPoints.length - 1]; - } - // Check if lastwaypoint is null or not - if (lastwaypoint === null) { - throw new Error("Last waypoint is null"); - } - // ref.getNextOrthogonalPoint(lastwaypoint, target); - const orthopoint = ref.getNextOrthogonalPoint(lastwaypoint, target); - ref.lastPoint = [orthopoint[0], orthopoint[1]]; - } else { - ref.lastPoint = [target[0], target[1]]; - } - if (ref.dragging) { - // This queue basically does the rendering of the connection feature - ref.updateQueue.run(); - } - - // This queue basically does the rendering of the target - ref.showQueue.run(); - }; - } - - /** - * This function renders the cross haired target used to show the mouse position. - * @param point - */ - showTarget(point: paper.Point): void { - const target = PositionTool.getTarget([point.x, point.y]); - Registry.viewManager?.updateTarget(this.typeString, this.setString, target); - } - - initChannel(): void { - if (this.lastPoint === null) { - throw new Error("No last point to init channel"); - } - const isPointOnComponent = this.__isPointOnComponent(new paper.Point(this.lastPoint)); - const isPointOnConnection = this.__isPointOnConnection(new paper.Point(this.lastPoint)); - this.startPoint = PositionTool.getTarget(this.lastPoint); - this.lastPoint = this.startPoint; - if (isPointOnComponent) { - // Modify the waypoint to reflect closest port in the future - const componentport = this.__getClosestComponentPort(isPointOnComponent, this.startPoint); - if (componentport !== null) { - const location = ComponentPort.calculateAbsolutePosition(componentport, isPointOnComponent); - this.source = new ConnectionTarget(isPointOnComponent, componentport.label); - this.startPoint = location; - this.lastPoint = this.startPoint; - this.wayPoints.push(location); - } else { - this.source = new ConnectionTarget(isPointOnComponent, ""); - this.wayPoints.push(this.startPoint); - } - } else if (isPointOnConnection) { - console.warn("Implement method to make the connection connections"); - // TODO: Find the current connection we are working with and load it into this tools working memory - this.__currentConnectionObject = isPointOnConnection; // We just use this as the reference - // TODO: Modify the waypoint to reflect the closest point on connection center spine - this.wayPoints.push(this.startPoint); - } else { - this.wayPoints.push(this.startPoint); - } - } - - updateChannel(): void { - if (this.lastPoint && this.startPoint) { - if (this.currentChannelID) { - const target = PositionTool.getTarget(this.lastPoint); - const feat = this.viewManagerDelegate.currentLayer?.getFeature(this.currentChannelID); - feat?.updateParameter("end", target); - feat?.updateParameter("wayPoints", this.wayPoints); - feat?.updateParameter("segments", this.generateSegments()); - } else { - if (this.startPoint === null) { - throw new Error("No start point to update the channel"); - } - const newChannel = this.createChannel(new paper.Point(this.startPoint), new paper.Point(this.startPoint)); - this.currentChannelID = newChannel.ID; - Registry.viewManager?.addFeature(newChannel); - } - } - } - - /** - * Finishes the creation of the connection object - */ - finishChannel(): void { - if (this.currentChannelID) { - this.wayPoints.push(this.lastPoint); - const feat = this.viewManagerDelegate.currentLayer.getFeature(this.currentChannelID); - feat?.updateParameter("end", this.lastPoint); - // feat.updateParameter("wayPoints", this.wayPoints); - feat?.updateParameter("segments", this.generateSegments()); - // Save the connection object - const rawparams = feat?.getParams(); - const values: { [k: string]: any } = {}; - for (const key in rawparams) { - values[key] = rawparams[key].value; - } - const definition = ComponentAPI.getDefinition("Connection"); - const params = new Params(values, MapUtils.toMap(definition!.unique), MapUtils.toMap(definition!.heritable)); - if (this.__currentConnectionObject === null || this.__currentConnectionObject === undefined) { - if (this.viewManagerDelegate.currentLayer.physicalLayer === null) throw new Error("Error: Attempting to add connection on non-physical layer"); - const connection = new Connection("Connection", params, Registry.currentDevice!.generateNewName("CHANNEL"), "CHANNEL", this.viewManagerDelegate.currentLayer.physicalLayer); - connection.routed = true; - connection.addFeatureID(feat!.ID); - connection.addWayPoints(this.wayPoints); - feat!.referenceID = connection.id; - this.__addConnectionTargets(connection); - Registry.currentDevice?.addConnection(connection); - } else { - // console.error("Implement conneciton tool to update existing connection"); - // TODO: Update the connection with more sinks and paths and what not - this.__currentConnectionObject.addFeatureID(feat!.ID); - feat!.referenceID = this.__currentConnectionObject.id; - this.__currentConnectionObject.addWayPoints(this.wayPoints); - feat!.referenceID = this.__currentConnectionObject.id; - this.__addConnectionTargets(this.__currentConnectionObject); - } - - this.currentChannelID = null; - this.wayPoints = []; - this.source = null; - this.sinks = []; - this.__currentConnectionObject = null; - Registry.viewManager?.saveDeviceState(); - } else { - console.error("Something is wrong here, unable to finish the connection"); - } - - Registry.viewManager?.saveDeviceState(); - } - - cleanup(): void { - console.log("Running Cleanup for the Connection Tool"); - - /* - Step 1 - Check the state - Step 2 - based on the state do the following - SOURCE - Do nothing, everything is good - WAYPOINT - 1) Reset the state to __source 2) cleanup features 3) TBA - TARGET - Set the state to SOURCE and do nothing else - */ - switch (this.__STATE) { - case ConnectionToolState.PLACE_FIRST_POINT: - console.log("Doing nothing"); - break; - case ConnectionToolState.PLACE_WAYPOINT: - console.warn("Paused connection placement midway"); - - break; - case ConnectionToolState.TARGET_PLACED_START_AGAIN: - this.__STATE = ConnectionToolState.PLACE_FIRST_POINT; - this.dragging = false; - break; - } - } - - /** - * Adds a way point to the connection - * @param event - * @param isManhatten - */ - addWayPoint(event: MouseEvent, isManhatten: boolean): void { - let connectiontargettoadd; - const point = MouseTool.getEventPosition(event); - const isPointOnComponent = this.__isPointOnComponent(point!); - const isPointOnConnection = this.__isPointOnConnection(point!); - if (point === null) return; - let target = PositionTool.getTarget([point.x, point.y]); - if (isManhatten && target) { - // TODO: modify the target to find the orthogonal point - let lastwaypoint = this.startPoint; - if (this.wayPoints.length > 0) { - lastwaypoint = this.wayPoints[this.wayPoints.length - 1]; - } - // Check if the lastwaypoint is null or not - if (lastwaypoint === null) { - throw new Error("Target is null"); - } - target = this.getNextOrthogonalPoint(lastwaypoint, target); - } - if (target.length == 2) { - this.wayPoints.push(target); - } - - if (isPointOnComponent) { - // Modify the waypoint to reflect closest port in the future - if (this.startPoint === null) { - throw new Error("No start point to update the channel"); - } - const componentport = this.__getClosestComponentPort(isPointOnComponent, this.startPoint, target); - if (componentport !== null) { - const location = ComponentPort.calculateAbsolutePosition(componentport, isPointOnComponent); - connectiontargettoadd = new ConnectionTarget(isPointOnComponent, componentport.label); - this.wayPoints.pop(); - this.lastPoint = location; - } else { - connectiontargettoadd = new ConnectionTarget(isPointOnComponent, ""); - this.lastPoint = this.wayPoints.pop(); - } - - // Do this if we want to terminate the connection - // Check if source is empty - if (this.source === null) { - // Set is as the source - // console.log("isPointOnComponent", isPointOnComponent); - this.source = connectiontargettoadd; - } else { - // Add it to the sinks - this.sinks.push(connectiontargettoadd); - } - this.__STATE = ConnectionToolState.TARGET_PLACED_START_AGAIN; // "TARGET"; - this.dragging = false; - this.finishChannel(); - } else if (isPointOnConnection) { - console.log("There is connection at the waypoint path"); - if (this.__currentConnectionObject === null) { - this.__currentConnectionObject = isPointOnConnection; - } else { - this.__currentConnectionObject.mergeConnection(isPointOnConnection); - } - this.__STATE = ConnectionToolState.TARGET_PLACED_START_AGAIN; //"TARGET"; - this.dragging = false; - this.lastPoint = this.wayPoints.pop(); - this.finishChannel(); - } - } - - /** - * Checks if the point coincides with a Connection. Return the Connection associated with the point or returns false - * @param point - * @return {boolean} or Connection Object - * @private - */ - __isPointOnConnection(point: paper.Point) { - // console.log("Point to check", point); - const render = Registry.viewManager?.hitFeature(point as unknown as number[]); - if (render !== false && render !== null && render !== undefined) { - let connection; - const feature = Registry.viewManager?.getFeatureByID(render.featureID); - // const feature = Registry.currentDevice.getFeatureByID(render.featureID); - // TODO: Replace this logic - if (feature!.referenceID === null) { - return false; - } else { - connection = Registry.currentDevice?.getConnectionByID(feature!.referenceID); - } - // console.log("Feature that intersects:", feature); - // console.log("Associated object:", connection); - return connection; - } - - return false; - } - - /** - * Checks if the point coincides with a component. Return the Component associated with the point or returns false - * @param point - * @return {boolean} or Component Object - * @private - */ - __isPointOnComponent(point: paper.Point) { - // console.log("Point to check", point); - const render = Registry.viewManager?.hitFeature(point as unknown as number[]); - - if (render !== false && render !== null && render !== undefined) { - let component; - const feature = Registry.viewManager?.getFeatureByID(render.featureID); - // const feature = Registry.currentDevice.getFeatureByID(render.featureID); - // console.log("Feature that intersects:", feature); - // TODO: Replace this logic - if (feature!.referenceID === null) { - return false; - } else { - component = Registry.currentDevice?.getComponentByID(feature!.referenceID); - } - // console.log("Associated object:", component); - if (component !== null || component !== undefined) { - return component; - } else { - return false; - } - } - - return false; - } - - /** - * Creates the channel from the start and the end point - * @param start - * @param end - * @return {EdgeFeature} - */ - createChannel(start: paper.Point, end: paper.Point) { - return Device.makeFeature(this.typeString, { - start: start, - end: end, - wayPoints: this.wayPoints, - segments: this.generateSegments() - }); - } - - /** - * Gets the closes manhatten point to where ever the mouse is - * @param lastwaypoint - * @param target - * @return {*} - */ - getNextOrthogonalPoint(lastwaypoint: Point, target: Point): Point { - // Trivial case where target is orthogonal - if (target[0] === lastwaypoint[0] || target[1] === lastwaypoint[1]) { - return target; - } - - const ret: Point = [target[0], target[1]]; - // Find out if the delta x or delta y is smaller and then just 0 the that coordinate - const delta_x = Math.abs(target[0] - lastwaypoint[0]); - const delta_y = Math.abs(target[1] - lastwaypoint[1]); - if (delta_x < delta_y) { - ret[0] = lastwaypoint[0]; - } else { - ret[1] = lastwaypoint[1]; - } - return ret; - } - - /** - * Goes through teh waypoints and generates the connection segments - * @return {Array} - */ - generateSegments() { - const waypointscopy = []; - waypointscopy.push(this.startPoint); - this.wayPoints.forEach(function (waypoint) { - waypointscopy.push(waypoint); - }); - // TODO: Fix this bullshit where teh points are not always arrays - if (Array.isArray(this.lastPoint)) { - waypointscopy.push(this.lastPoint); - } else { - waypointscopy.push(this.lastPoint); - } - // console.log("waypoints", this.wayPoints, this.startPoint); - const ret = []; - for (let i = 0; i < waypointscopy.length - 1; i++) { - const segment = [waypointscopy[i], waypointscopy[i + 1]]; - ret.push(segment); - } - // console.log("segments:", ret); - return ret; - } - - /** - * Checks if the current connection tool object has source and sinks and updates the connection object that is - * passed as an argument in this method. - * @private - */ - __addConnectionTargets(connection: Connection): void { - if (this.source !== null && this.source !== undefined) { - connection.addConnectionTarget(this.source); - } - - for (const i in this.sinks) { - console.log("Sinks: ", this.sinks); - connection.addConnectionTarget(this.sinks[i]); - } - } - - /** - * Returns the closest component port to the given point - * @param component - * @param startPoint - * @param targetPoint This is null in case of the initialzing case - * @return {ComponentPort} - * @private - */ - __getClosestComponentPort(component: any, startPoint: Point, targetPoint: Point | null = null) { - // console.log("Location of startpoint: ",startPoint); - // Find out if this is on control or flow for now - // TODO:Change this implementation, currently layer does not have a type setting that maps 1-1 to the componentport layer location - let closest; - let layertype = null; - let dist; - const gridsize = Registry.currentGrid?.getSpacing(); - console.log("Grid Size: ", gridsize); - - if (this.viewManagerDelegate.currentLayer.type === LogicalLayerType.CONTROL) { - layertype = "CONTROL"; - } else if (this.viewManagerDelegate.currentLayer.type === LogicalLayerType.FLOW) { - layertype = "FLOW"; - } else if (this.viewManagerDelegate.currentLayer.type === LogicalLayerType.INTEGRATION) { - layertype = "INTEGRATION"; - } - console.log("This layer: ", layertype); - const componentports = component.ports; - if (layertype === null) { - console.warn("Could not find the current layer type, searching through all the component ports without filtering"); - } - - // TODO: Check if the targetPoint and the component port are closer than grid size, if they are just make the connection - if (targetPoint !== null) { - for (const key of componentports.keys()) { - const componentport = componentports.get(key); - if (componentport.layer !== layertype) { - continue; - } - const location = ComponentPort.calculateAbsolutePosition(componentport, component); - const calc = Math.abs(targetPoint[0] - location[0]) + Math.abs(targetPoint[1] - location[1]); - // let gridsize = 1000; //TODO:Calculate from grid size - // Check if anything is really really close (use current grid size for now) to the port. - if (calc <= 3 * gridsize!) { - // If the distance is really small then yes fix return it - return componentport; - } - } - } - - dist = 1000000000000000; - closest = null; - for (const key of componentports.keys()) { - const componentport = componentports.get(key); - if (componentport.layer !== layertype) { - continue; - } - const location = ComponentPort.calculateAbsolutePosition(componentport, component); - const calc = Math.abs(startPoint[0] - location[0]) + Math.abs(startPoint[1] - location[1]); - if (calc < dist) { - dist = calc; - closest = componentport; - } - } - - return closest; - } - - /** - * Updates the parameters of the connection object - * - * @param {string} parameter - * @param {*} value - * @memberof ConnectionTool - */ - updateParameter(parameter: string, value: any): void { - if(this.currentChannelID !== null){ - const feat = this.viewManagerDelegate.currentLayer.getFeature(this.currentChannelID); - feat?.updateParameter(parameter, value); - } - } -} diff --git a/src/app/view/tools/customComponentPositionTool.ts b/src/app/view/tools/customComponentPositionTool.ts deleted file mode 100644 index 257b3b3e..00000000 --- a/src/app/view/tools/customComponentPositionTool.ts +++ /dev/null @@ -1,78 +0,0 @@ -import paper from "paper"; -import PositionTool from "./positionTool"; -import Registry from "../../core/registry"; -import Feature from "../../core/feature"; -import CustomComponent from "../../core/customComponent"; -import Params from "../../core/params"; -import Component from "../../core/component"; -import ViewManager from "../viewManager"; -import { ComponentAPI } from "@/componentAPI"; - -export default class CustomComponentPositionTool extends PositionTool { - private __customComponent: CustomComponent; - - constructor(viewManagerDelegate: ViewManager, customcomponent: CustomComponent, setString: string) { - super(viewManagerDelegate, customcomponent.type); - - this.__customComponent = customcomponent; - } - - createNewFeature(point: paper.Point): void { - const featureIDs = []; - // console.log("Custom Component:", this.__customComponent); - - const newFeature = Feature.makeCustomComponentFeature(this.__customComponent, this.setString, { - position: PositionTool.getTarget([point.x, point.y]) - }); - this.currentFeatureID = newFeature.ID; - - Registry.viewManager?.addFeature(newFeature); - - featureIDs.push(newFeature.ID); - - const params_to_copy = newFeature.getParams(); - - // TODO: Change the component generation - this.createNewCustomComponent(params_to_copy, featureIDs); - Registry.viewManager?.saveDeviceState(); - } - - showTarget(): void { - if (this.lastPoint === null) { - throw new Error("No last point"); - } - const target = PositionTool.getTarget(this.lastPoint); - Registry.viewManager?.updateTarget(this.typeString, this.setString, target, {}); - } - - createNewCustomComponent(paramdata: { [k: string]: any }, featureIDs: string[]) { - const definition = CustomComponent.defaultParameterDefinitions(); - // Clean Param Data - const cleanparamdata: { [k: string]: any } = {}; - for (const key in paramdata) { - cleanparamdata[key] = paramdata[key].value; - } - // console.log(cleanparamdata); - const params = new Params(cleanparamdata, definition.unique as unknown as Map, definition.heritable as unknown as Map); - const componentid = ComponentAPI.generateID(); - console.log(this.__customComponent.entity, this.__customComponent.type); - // Check if currentDevice is null or not - if (Registry.currentDevice === null) { - throw new Error("No current device"); - } - const name = Registry.currentDevice.generateNewName(this.__customComponent.entity); - const newComponent = new Component(params, name, this.__customComponent.entity, componentid); - let feature; - - for (const i in featureIDs) { - newComponent.addFeatureID(featureIDs[i]); - - // Update the component reference - feature = Registry.currentDevice?.getFeatureByID(featureIDs[i]); - feature!.referenceID = componentid; - } - - Registry.currentDevice?.addComponent(newComponent); - return newComponent; - } -} diff --git a/src/app/view/tools/generateArrayTool.ts b/src/app/view/tools/generateArrayTool.ts deleted file mode 100644 index c4091d1f..00000000 --- a/src/app/view/tools/generateArrayTool.ts +++ /dev/null @@ -1,261 +0,0 @@ -import MouseTool, { MouseToolCallback } from "./mouseTool"; - -import Registry from "../../core/registry"; -import SimpleQueue from "../../utils/simpleQueue"; -import Component from "@/app/core/component"; -import ViewManager from "../viewManager"; - -export default class GenerateArrayTool extends MouseTool { - private __currentComponent?: any; - private __originalPosition?: any; - - /** - * Creates an instance of GenerateArrayTool. - * @memberof GenerateArrayTool - */ - constructor(viewManagerDelegate: ViewManager) { - super(viewManagerDelegate); - - // this.dragging = false; - // this.dragStart = null; - // this.lastPoint = null; - // this.currentSelectBox = null; - // this.currentSelection = []; - const ref = this; - // this.updateQueue = new SimpleQueue(function () { - // ref.dragHandler(); - // }, 20); - this.down = function(event) { - // Registry.viewManager.killParamsWindow(); - ref.mouseDownHandler(event); - // ref.dragging = true; - // ref.showTarget(); - }; - this.move = function(event) { - // if (ref.dragging) { - // ref.lastPoint = MouseTool.getEventPosition(event); - // ref.updateQueue.run(); - // } - // ref.showTarget(); - }; - this.up = function(event) { - // ref.dragging = false; - ref.mouseUpHandler(event); - // ref.showTarget(); - }; - } - - activate(component: Component): void { - console.log("Activating the tool for a new component", component); - // Store the component position here - this.__currentComponent = component; - } - - deactivate(): void { - Registry.viewManager?.resetToDefaultTool(); - } - - generateArray(xdim: number, ydim: number, xspacing: number, yspacing: number): void { - console.log("Generate array:", xdim, ydim, xspacing, yspacing); - const xposref = this.__currentComponent.getPosition()[0]; - const yposref = this.__currentComponent.getPosition()[1]; - const name = this.__currentComponent.name; - this.__currentComponent.name = name + "_1_1"; - const replicas = []; - // Loop to create the components at the new positions - for (let y = 0; y < ydim; y++) { - for (let x = 0; x < xdim; x++) { - // Skip the x=0, y=0 because thats the initial one - if (x === 0 && y === 0) { - continue; - } - const xpos = xposref + x * xspacing; - const ypos = yposref + y * yspacing; - replicas.push(this.__currentComponent.replicate(xpos, ypos, name + "_" + String(x + 1) + "_" + String(y + 1))); - } - } - - // Add the replicas to the device - console.log(replicas); - replicas.forEach(function(replica) { - Registry.currentDevice?.addComponent(replica); - }); - - Registry.viewManager?.saveDeviceState(); - } - - revertToOriginalPosition(): void { - this.__currentComponent.updateComponentPosition(this.__originalPosition); - } - - dragHandler(): void { - // if (this.dragStart) { - // if (this.currentSelectBox) { - // this.currentSelectBox.remove(); - // } - // this.currentSelectBox = this.rectSelect(this.dragStart, this.lastPoint); - // } - } - - // showTarget() { - // Registry.viewManager.removeTarget(); - // } - - mouseUpHandler(event: MouseEvent): void { - // if (this.currentSelectBox) { - // this.currentSelection = Registry.viewManager.hitFeaturesWithViewElement(this.currentSelectBox); - // this.selectFeatures(); - // } - // this.killSelectBox(); - console.log("Up event", event); - } - - mouseDownHandler(event: MouseEvent): void { - // let point = MouseTool.getEventPosition(event); - // let target = this.hitFeature(point); - // if (target) { - // if (target.selected) { - // let feat = Registry.currentDevice.getFeatureByID(target.featureID); - // Registry.viewManager.updateDefaultsFromFeature(feat); - // let rightclickmenu = new RightClickMenu(feat); - // rightclickmenu.show(event); - // Registry.viewManager.rightClickMenu = rightclickmenu; - // this.rightClickMenu = rightclickmenu; - // // let func = PageSetup.getParamsWindowCallbackFunction(feat.getType(), feat.getSet()); - // //func(event); - // } else { - // this.deselectFeatures(); - // this.selectFeature(target); - // } - // - // - // } else { - // this.deselectFeatures(); - // this.dragStart = point; - // } - console.log("Down event", event); - } - - // killSelectBox() { - // if (this.currentSelectBox) { - // this.currentSelectBox.remove(); - // this.currentSelectBox = null; - // } - // this.dragStart = null; - // } - // - // hitFeature(point) { - // let target = Registry.viewManager.hitFeature(point); - // return target; - // } - - /** - * Function that is fired when we click to select a single object on the paperjs canvas - * @param paperElement - */ - // selectFeature(paperElement) { - // this.currentSelection.push(paperElement); - // - // //Find the component that owns this feature and then select all of the friends - // let component = this.__getComponentWithFeatureID(paperElement.featureID); - // if (component === null) { - // //Does not belong to a component, hence this returns - // paperElement.selected = true; - // - // } else { - // //Belongs to the component so we basically select all features with this id - // let featureIDs = component.featureIDs; - // for (let i in featureIDs) { - // let featureid = featureIDs[i]; - // let actualfeature = Registry.viewManager.view.paperFeatures[featureid]; - // actualfeature.selected = true; - // } - // - // Registry.viewManager.view.selectedComponents.push(component); - // } - // } - - // /** - // * Finds and return the corresponding Component Object in the Registry's current device associated with - // * the featureid. Returns null if no component is found. - // * - // * @param featureid - // * @return {Component} - // * @private - // */ - // __getComponentWithFeatureID(featureid) { - // // Get component with the features - // - // let device_components = Registry.currentDevice.components; - // - // //Check against every component - // for (let i in device_components) { - // let component = device_components[i]; - // //Check against features in the in the component - // let componentfeatures = component.featureIDs; - // let index = componentfeatures.indexOf(featureid); - // - // if (index !== -1) { - // //Found it !! - // console.log("Found Feature: " + featureid + " in component: " + component.getID()); - // return component; - // } - // } - // - // return null; - // } - - /** - * Function that is fired when we drag and select an area on the paperjs canvas - */ - // selectFeatures() { - // if (this.currentSelection) { - // for (let i = 0; i < this.currentSelection.length; i++) { - // let paperFeature = this.currentSelection[i]; - // - // //Find the component that owns this feature and then select all of the friends - // let component = this.__getComponentWithFeatureID(paperFeature.featureID); - // - // if (component === null) { - // //Does not belong to a component hence do the normal stuff - // paperFeature.selected = true; - // - // } else { - // //Belongs to the component so we basically select all features with this id - // let featureIDs = component.featureIDs; - // for (let i in featureIDs) { - // let featureid = featureIDs[i]; - // let actualfeature = Registry.viewManager.view.paperFeatures[featureid]; - // actualfeature.selected = true; - // } - // - // Registry.viewManager.view.selectedComponents.push(component); - // } - // - // } - // } - // } - - // deselectFeatures() { - // if(this.rightClickMenu){ - // this.rightClickMenu.close(); - // this.rightClickMenu = null; - // } - // paper.project.deselectAll(); - // this.currentSelection = []; - // } - - // abort() { - // this.deselectFeatures(); - // this.killSelectBox(); - // } - - // rectSelect(point1, point2) { - // let rect = new paper.Path.Rectangle(point1, point2); - // rect.fillColor = new paper.Color(0, .3, 1, .4); - // rect.strokeColor = new paper.Color(0, 0, 0); - // rect.strokeWidth = 2; - // rect.selected = true; - // return rect; - // } -} diff --git a/src/app/view/tools/insertTextTool.ts b/src/app/view/tools/insertTextTool.ts deleted file mode 100644 index d6cb24a7..00000000 --- a/src/app/view/tools/insertTextTool.ts +++ /dev/null @@ -1,98 +0,0 @@ -import MouseTool, { MouseToolCallback } from "./mouseTool"; -import Device from "@/app/core/device"; -import Registry from "../../core/registry"; -import SimpleQueue from "../../utils/simpleQueue"; - -import paper from "paper"; -import PositionTool from "./positionTool"; -import Params from "../../core/params"; -import { ComponentAPI } from "@/componentAPI"; -import { ViewManager } from "@/app"; -import { Point } from "@/app/core/init"; - -export default class InsertTextTool extends MouseTool { - typeString: string; - setString: string; - currentFeatureID: string | null; - lastPoint: Point | null; - - private _text: string; - fontSize: number; - viewManagerDelegate: ViewManager; - showQueue: SimpleQueue; - - constructor(viewManager: ViewManager) { - super(viewManager); - this.typeString = "TEXT"; - this.setString = "Standard"; - this.currentFeatureID = null; - const ref = this; - this.lastPoint = null; - this._text = "TESTING-TEXT"; - this.fontSize = 12; - this.viewManagerDelegate = viewManager; - this.showQueue = new SimpleQueue( - function() { - ref.showTarget(); - }, - 20, - false - ); - this.up = function(event) { - // do nothing - }; - this.move = function(event) { - let point = MouseTool.getEventPosition((event as unknown) as MouseEvent); - if(point === null) { - return; - } - ref.lastPoint = [point.x, point.y]; - ref.showQueue.run(); - }; - this.down = function(event) { - Registry.viewManager?.killParamsWindow(); - paper.project.deselectAll(); - // TODO - Add the ability to insert a non physical text element later on using Liam's Nonphysical compoennt API - ref.createNewFeature(MouseTool.getEventPosition((event as unknown) as MouseEvent) as paper.Point); - }; - } - - /** - * Creates a physical test feature when using the InsertTextTool - */ - createNewFeature(point: paper.Point): void { - let fixedpoint = PositionTool.getTarget([point.x, point.y]); - let newFeature = Device.makeFeature( - "Text", - { - position: fixedpoint, - height: 200, - text: this._text, - fontSize: this.fontSize * 10000 - }, - "TEXT_" + this._text, - ComponentAPI.generateID(), - "XY", - null - ); - this.viewManagerDelegate.addFeature(newFeature, this.viewManagerDelegate.activeRenderLayerIndex); - this.viewManagerDelegate.view.addComponent("Text", newFeature.getParams(), [newFeature.ID], true); - this.viewManagerDelegate.saveDeviceState(); - } - - showTarget(): void { - if (this.lastPoint === null) { - return; - } - const target = PositionTool.getTarget(this.lastPoint); - Registry.viewManager?.updateTarget(this.typeString, this.setString, target, {}); - } - - get text() { - return this._text; - } - - set text(text) { - this._text = text; - } -} diff --git a/src/app/view/tools/mouseSelectTool.ts b/src/app/view/tools/mouseSelectTool.ts deleted file mode 100644 index aa8ed411..00000000 --- a/src/app/view/tools/mouseSelectTool.ts +++ /dev/null @@ -1,294 +0,0 @@ -import MouseTool, { MouseToolCallback } from "./mouseTool"; - -import Registry from "../../core/registry"; -import SimpleQueue from "../../utils/simpleQueue"; -import paper from "paper"; -import EventBus from "@/events/events"; -import ViewManager from "@/app/view/viewManager"; -import PaperView from "@/app/view/paperView"; - -export default class MouseSelectTool extends MouseTool { - paperView: PaperView; - - dragging: boolean; - - dragStart: paper.Point | null; - lastPoint: paper.Point | number[] | null; - - currentSelectBox: any; - - currentSelection: any[]; - - updateQueue: SimpleQueue; - - constructor(viewManager: ViewManager, paperview: PaperView) { - super(viewManager); - this.viewManagerDelegate = viewManager; - this.paperView = paperview; - this.dragging = false; - this.dragStart = null; - this.lastPoint = null; - this.currentSelectBox = null; - this.currentSelection = []; - const ref = this; - this.updateQueue = new SimpleQueue(function () { - ref.dragHandler(); - }, 20); - this.down = function (event) { - ref.viewManagerDelegate.killParamsWindow(); - ref.mouseDownHandler(event); - ref.dragging = true; - ref.showTarget(); - }; - this.move = function (event) { - if (ref.dragging) { - ref.lastPoint = MouseTool.getEventPosition(event as unknown as MouseEvent) as unknown as number[]; - ref.updateQueue.run(); - } - ref.showTarget(); - }; - this.up = function (event) { - ref.dragging = false; - ref.mouseUpHandler(MouseTool.getEventPosition(event as unknown as MouseEvent)!); - ref.showTarget(); - }; - } - - keyHandler(event: KeyboardEvent): void { - if (event.key === "delete" || event.key === "backspace") { - console.log("Removing feature"); - this.removeFeatures(); - } - if (event.key === "c") { - console.log("Detected a ctrlC"); - console.log(this.currentSelection); - } - } - - dragHandler(): void { - if (this.dragStart) { - if (this.currentSelectBox) { - this.currentSelectBox.remove(); - } - this.currentSelectBox = this.rectSelect(this.dragStart, this.lastPoint as paper.Point); - } - } - - showTarget(): void { - this.viewManagerDelegate.removeTarget(); - } - - mouseUpHandler(point: paper.Point): void { - if (this.currentSelectBox) { - this.currentSelection = this.viewManagerDelegate.hitFeaturesWithViewElement(this.currentSelectBox); - this.selectFeatures(); - } - this.killSelectBox(); - } - - removeFeatures(): void { - if (this.currentSelection.length > 0) { - for (let i = 0; i < this.currentSelection.length; i++) { - const paperFeature = this.currentSelection[i]; - let devicefeature = Registry.currentDevice?.getFeatureByID(paperFeature.featureID); - Registry.currentDevice?.removeFeature(devicefeature!); - } - this.currentSelection = []; - // Registry.canvasManager?.render(); - } - } - - mouseDownHandler(event: MouseEvent): void { - const point = MouseTool.getEventPosition(event as unknown as MouseEvent); - const target = this.hitFeature(point as unknown as number[]); - if (target) { - if (target.selected) { - const feat = this.viewManagerDelegate.getFeatureByID(target.featureID); - this.viewManagerDelegate.updateDefaultsFromFeature(feat); - // Check if the feature is a part of a component - let component, connection; - if (feat.referenceID === null) { - throw new Error("ReferenceID of feature is null"); - } else { - component = Registry.currentDevice?.getComponentByID(feat.referenceID); - connection = Registry.currentDevice?.getConnectionByID(feat.referenceID); - if (component !== null) { - (EventBus as any).get().emit(EventBus.DBL_CLICK_COMPONENT, event, component); - } else if (connection !== null) { - (EventBus as any).get().emit(EventBus.DBL_CLICK_CONNECTION, event, connection); - } else { - (EventBus as any).get().emit(EventBus.DBL_CLICK_FEATURE, event, feat); - } - } - - // const rightclickmenu = this.viewManagerDelegate.rightClickMenu; // new RightClickMenu(feat); - // rightclickmenu.show(event, feat); - // this.rightClickMenu = rightclickmenu; - // let func = PageSetup.getParamsWindowCallbackFunction(feat.getType(), feat.getSet()); - // func(event); - } else { - this.deselectFeatures(); - this.selectFeature(target); - } - } else { - this.deselectFeatures(); - this.dragStart = point!; - } - } - - killSelectBox(): void { - if (this.currentSelectBox) { - this.currentSelectBox.remove(); - this.currentSelectBox = null; - } - this.dragStart = null; - } - - hitFeature(point: number[]) { - const target = this.viewManagerDelegate.hitFeature(point); - return target; - } - - /** - * Function that is fired when we click to select a single object on the paperjs canvas - * @param paperElement - */ - selectFeature(paperElement: any): void { - this.currentSelection.push(paperElement); - - // Find the component that owns this feature and then select all of the friends - const component = this.__getComponentWithFeatureID(paperElement.featureID); - const connection = this.__getConnectionWithFeatureID(paperElement.featureID); - if (component === null && connection === null) { - // Does not belong to a component, hence this returns - paperElement.selected = true; - } else if (component !== null) { - // Belongs to the component so we basically select all features with this id - const featureIDs = component.featureIDs; - for (const i in featureIDs) { - const featureid = featureIDs[i]; - const actualfeature = this.viewManagerDelegate.view.paperFeatures[featureid]; - actualfeature.selected = true; - } - - this.viewManagerDelegate.view.selectedComponents.push(component); - } else if (connection !== null) { - const featureIDs = connection.featureIDs; - for (const i in featureIDs) { - const featureid = featureIDs[i]; - const actualfeature = this.viewManagerDelegate.view.paperFeatures[featureid]; - actualfeature.selected = true; - } - - this.viewManagerDelegate.view.selectedConnections.push(connection); - } else { - throw new Error("Totally got the selection logic wrong, reimplement this"); - } - } - - /** - * Finds and return the corresponding Component Object in the Registry's current device associated with - * the featureid. Returns null if no component is found. - * - * @param featureid - * @return {Component} - * @private - */ - __getComponentWithFeatureID(featureid: string) { - // Get component with the features - - const device_components = Registry.currentDevice!.components; - - // Check against every component - for (const i in device_components) { - const component = device_components[i]; - // Check against features in the in the component - const componentfeatures = component.featureIDs; - const index = componentfeatures.indexOf(featureid); - - if (index !== -1) { - // Found it !! - return component; - } - } - - return null; - } - - /** - * Finds and return the corresponding Connection Object in the Registry's current device associated with - * the featureid. Returns null if no connection is found. - * - * @param featureid - * @return {*} - * @private - */ - __getConnectionWithFeatureID(featureid: string) { - // Get component with the features - - const device_connections = Registry.currentDevice!.connections; - - // Check against every component - for (const i in device_connections) { - const connection = device_connections[i]; - // Check against features in the in the component - const connection_features = connection.featureIDs; - const index = connection_features.indexOf(featureid); - - if (index !== -1) { - // Found it !! - return connection; - } - } - - return null; - } - - /** - * Function that is fired when we drag and select an area on the paperjs canvas - */ - selectFeatures(): void { - if (this.currentSelection) { - for (let i = 0; i < this.currentSelection.length; i++) { - const paperFeature = this.currentSelection[i]; - - // Find the component that owns this feature and then select all of the friends - const component = this.__getComponentWithFeatureID(paperFeature.featureID); - - if (component === null) { - // Does not belong to a component hence do the normal stuff - paperFeature.selected = true; - } else { - // Belongs to the component so we basically select all features with this id - const featureIDs = component.featureIDs; - for (const j in featureIDs) { - const featureid = featureIDs[j]; - const actualfeature = this.viewManagerDelegate.view.paperFeatures[featureid]; - actualfeature.selected = true; - } - - this.viewManagerDelegate.view.selectedComponents.push(component); - } - } - } - } - - deselectFeatures(): void { - this.paperView.clearSelectedItems(); - this.currentSelection = []; - } - - abort(): void { - this.deselectFeatures(); - this.killSelectBox(); - } - - rectSelect(point1: paper.Point, point2: paper.Point) { - const rect = new paper.Path.Rectangle(point1, point2); - rect.fillColor = new paper.Color(0, 0.3, 1, 0.4); - rect.strokeColor = new paper.Color(0, 0, 0); - rect.strokeWidth = 2; - rect.selected = true; - return rect; - } -} diff --git a/src/app/view/tools/mouseTool.ts b/src/app/view/tools/mouseTool.ts deleted file mode 100644 index 01070914..00000000 --- a/src/app/view/tools/mouseTool.ts +++ /dev/null @@ -1,97 +0,0 @@ -import paper from "paper"; -import Registry from "../../core/registry"; -import ViewManager from "../viewManager"; - -export interface MouseToolCallback { - (event: MouseEvent): void; -} -export default class MouseTool { - - viewManagerDelegate: ViewManager; - - /** - * Creates an instance of MouseTool. This is the base class for all mouse tools. - * @memberof MouseTool - */ - constructor(viewManagerDelegate: ViewManager) { - this.viewManagerDelegate = viewManagerDelegate; - } - - /** - * This function is called when the mouse is released. - * - * @param {MouseEvent} event - * @memberof MouseTool - */ - up(event: MouseEvent): void { - MouseTool.defaultFunction("up"); - } - - /** - * This function is called when the mouse is pressed. - * - * @param {MouseEvent} event - * @memberof MouseTool - */ - down(event: MouseEvent): void { - MouseTool.defaultFunction("down"); - } - - /** - * This function is called when the mouse is moved. - * - * @param {MouseEvent} event - * @memberof MouseTool - */ - move(event: MouseEvent): void { - MouseTool.defaultFunction("move"); - } - - /** - * This function is called when the right mouse button is clicked. - * - * @param {MouseEvent} event - * @memberof MouseTool - */ - rightdown(event: MouseEvent): void { - MouseTool.defaultFunction("rightdown"); - } - - /** - * This fucntion is a convenience function that can be called to clean up the tool. - * - * @memberof MouseTool - */ - cleanup(): void { - console.log("Default Message: You have to implement the method cleanup!"); - } - - /** - * This is the dummy function that is called when no function is set. - * - * @static - * @param {string} value - * @returns - * @memberof MouseTool - */ - static defaultFunction(value: string) { - return function(): void { - console.log("No " + value + " function set."); - }; - } - - /** - * This function returns the position of the mouse event in the paper coordinate system. - * - * @static - * @param {MouseEvent} event - * @returns {paper.Point} - * @memberof MouseTool - */ - static getEventPosition(event: MouseEvent):paper.Point { - if (Registry.viewManager !== null) { - return Registry.viewManager.getEventPosition(event); - } - throw new Error("No view manager set!"); - } -} diff --git a/src/app/view/tools/moveTool.ts b/src/app/view/tools/moveTool.ts deleted file mode 100644 index a334e804..00000000 --- a/src/app/view/tools/moveTool.ts +++ /dev/null @@ -1,169 +0,0 @@ -import MouseTool from "./mouseTool"; -import paper from "paper"; -import Registry from "../../core/registry"; -import { Point } from "@/app/core/init"; -import ViewManager from "../viewManager"; - -export default class MoveTool extends MouseTool { - private __startPoint: Point | null; - private __dragging: boolean; - - private __currentComponent: any; - private __originalPosition: Point | null = null; - private _viewManagerDelegate: ViewManager; - - callback: ((...args: any[]) => any) | null; - - constructor(viewManagerDelegate: ViewManager) { - super(viewManagerDelegate); - - // Use the startpoint to calculate the delta for movement - this.__startPoint = null; - this.__dragging = false; - this.callback = null; - - this._viewManagerDelegate = viewManagerDelegate; - - // this.dragging = false; - // this.dragStart = null; - // this.lastPoint = null; - // this.currentSelectBox = null; - // this.currentSelection = []; - const ref = this; - // this.updateQueue = new SimpleQueue(function () { - // ref.dragHandler(); - // }, 20); - this.down = function (event) { - // Registry.viewManager.killParamsWindow(); - ref.mouseDownHandler(event as unknown as MouseEvent); - // ref.dragging = true; - // ref.showTarget(); - }; - this.move = function (event) { - // if (ref.dragging) { - // ref.lastPoint = MouseTool.getEventPosition(event); - // ref.updateQueue.run(); - // } - // ref.showTarget(); - ref.dragHandler(event as unknown as MouseEvent); - }; - this.up = function (event) { - // ref.dragging = false; - ref.mouseUpHandler(event as unknown as MouseEvent); - // ref.showTarget(); - }; - } - - /** - * Default activation method - * @param component - */ - activate(component: any, callback: (...args: any[]) => any): void { - // console.log("Activating the tool for a new component", component); - // Store the component position here - this.__currentComponent = component; - this.__originalPosition = component.getPosition(); - this.callback = callback; - } - - /** - * Default deactivation method - */ - deactivate(): void { - this._viewManagerDelegate.resetToDefaultTool(); - } - - /** - * Method that can process the update of the component position - * @param xpos - * @param ypos - */ - processUIPosition(xpos: number, ypos: number): void { - this.__currentComponent.updateComponentPosition([xpos, ypos]); - this.callback!(xpos, ypos); - } - - /** - * Updates the position of the current selected component - * @param xpos - * @param ypos - * @private - */ - __updatePosition(xpos: number, ypos: number): void { - this.processUIPosition(xpos, ypos); - } - - /** - * Reverts the position to the original position - */ - revertToOriginalPosition(): void { - this.__currentComponent.updateComponentPosition(this.__originalPosition); - } - - /** - * Function that handles the dragging of the mouse - * @param event - */ - dragHandler(event: MouseEvent): void { - if (this._viewManagerDelegate === null) { - throw new Error("No view manager set!"); - } - if (this.__dragging) { - const point = MouseTool.getEventPosition(event); - let target: paper.Point = new paper.Point(point.x, point.y); - if (point !== null && point !== undefined) { - let snappoint = this._viewManagerDelegate.snapToGrid([point.x, point.y]); - target = new paper.Point(snappoint[0], snappoint[1]); - } - // const delta = { - // x: (target).x - this.__startPoint[0], - // y: (target).y - this.__startPoint[1] - // }; - this.__startPoint = [target.x, target.y]; - // console.log("delta:", delta); - - // let oldposition = this.__currentComponent.getPosition(); - // // console.log("oldposition:", oldposition); - // - // let newposition = [oldposition[0] + delta.x, oldposition[1] + delta.y]; - // console.log("Newposition:", newposition); - // this.__currentComponent.updateComponentPosition(newposition); - this.__updatePosition(target.x, target.y); - } - } - - // showTarget() { - // Registry.viewManager.removeTarget(); - // } - - /** - * Method that handles the mouse up event - * @param event - */ - mouseUpHandler(event: MouseEvent): void { - const point = MouseTool.getEventPosition(event); - if (point === null){ - throw new Error("Point is null for move tool event handler"); - } - const targettosnap: Point = [point.x, point.y]; - const target = this._viewManagerDelegate.snapToGrid(targettosnap); - - // console.log("Start:",this.__startPoint, "End:" ,target); - this.__dragging = false; - } - - /** - * Method that handles the movement of the mouse cursor - * @param event - */ - mouseDownHandler(event: MouseEvent): void { - const point = MouseTool.getEventPosition(event); - if (point === null){ - throw new Error("Point is null for move tool event handler"); - } - const targettosnap: Point = [point.x, point.y]; - const target = this._viewManagerDelegate.snapToGrid(targettosnap); - this.__startPoint = target; - this.__dragging = true; - } -} diff --git a/src/app/view/tools/multilayerPositionTool.ts b/src/app/view/tools/multilayerPositionTool.ts deleted file mode 100644 index 5f8671ae..00000000 --- a/src/app/view/tools/multilayerPositionTool.ts +++ /dev/null @@ -1,63 +0,0 @@ -import PositionTool from "./positionTool"; -import { ComponentAPI } from "@/componentAPI"; -import Registry from "../../core/registry"; -import Device from "../../core/device"; -import ViewManager from "@/app/view/viewManager"; -import paper from "paper"; -import Parameter from "@/app/core/parameter"; - -export default class MultilayerPositionTool extends PositionTool { - constructor(viewManagerDelegate: ViewManager, typeString: string, setString: string, currentParameters: { [k: string]: any } | null = null) { - super(viewManagerDelegate, typeString, currentParameters); - } - - createNewFeature(point: paper.Point): void { - const featureIDs = []; - const currentlevel = Math.floor(Registry.viewManager!.renderLayers.indexOf(this.viewManagerDelegate.currentLayer!) / 3); - const flowlayer = currentlevel * 3; - const controllayer = currentlevel * 3 + 1; - const intlayer = currentlevel * 3 + 2; - - // Set up flow layer component - const paramvalues = this.getCreationParameters(new paper.Point(0, 0)); - let newFeature = Device.makeFeature(this.typeString, paramvalues); - this.currentFeatureID = newFeature.ID; - this.viewManagerDelegate.addFeature(newFeature, flowlayer); - const params_to_copy = newFeature.getParams(); - featureIDs.push(newFeature.ID); - - let newtypestring; - if (ComponentAPI.library[this.typeString + "_control"]) { - newtypestring = this.typeString + "_control"; - newFeature = Device.makeFeature(newtypestring, paramvalues); - - this.currentFeatureID = newFeature.ID; - this.viewManagerDelegate.addFeature(newFeature, controllayer); - - featureIDs.push(newFeature.ID); - } - - // Set up integration layer component - if (ComponentAPI.library[this.typeString + "_integration"]) { - newtypestring = this.typeString + "_integration"; - newFeature = Device.makeFeature(newtypestring, paramvalues); - - this.currentFeatureID = newFeature.ID; - this.viewManagerDelegate.addFeature(newFeature, intlayer); - - featureIDs.push(newFeature.ID); - } - - params_to_copy["position"] = new Parameter("position", [point.x, point.y]); - super.createNewComponent(this.typeString, params_to_copy, featureIDs); - Registry.viewManager?.saveDeviceState(); - } - - showTarget(): void { - if (this.lastPoint === null) { - return; - } - const target = PositionTool.getTarget(this.lastPoint); - this.viewManagerDelegate.updateTarget(this.typeString, this.setString, target, this.currentParameters!); - } -} diff --git a/src/app/view/tools/multilevelPositionTool.ts b/src/app/view/tools/multilevelPositionTool.ts deleted file mode 100644 index 293644c6..00000000 --- a/src/app/view/tools/multilevelPositionTool.ts +++ /dev/null @@ -1,118 +0,0 @@ -import PositionTool from "./positionTool"; -import { ComponentAPI } from "@/componentAPI"; -import Registry from "../../core/registry"; -import Device from "../../core/device"; -import ViewManager from "@/app/view/viewManager"; -import Layer from "@/app/core/layer"; -import RenderLayer from "../renderLayer"; -import paper from "paper"; - -export default class MultilevelPositionTool extends PositionTool { - flowlayer: RenderLayer | null; - controllayer: RenderLayer | null; - intlayer: RenderLayer | null; - - /** - * Creates an instance of MultilevelPositionTool. - * @param {ViewManager} viewManager - * @param {string} typeString - * @param {string} setString - * @param {*} [currentParameters=null] - * @memberof MultilevelPositionTool - */ - constructor( - viewManager: ViewManager, - typeString: string, - setString: string, - // flowLayer = this.currentLayer, - // controlLayer = null, - // intLayer = null, - currentParameters = null - ) { - super(viewManager, typeString, currentParameters); - let [flowLayer, controlLayer, intLayer] = this.viewManagerDelegate.getCurrentLevelRenderLayers(); - if (flowLayer === null) { - throw new Error("Flow layer is null"); - } else { - this.flowlayer = flowLayer; - } - if (controlLayer === null) { - throw new Error("Control layer is null"); - } - if (intLayer === null) { - throw new Error("Integration layer is null"); - } - this.controllayer = controlLayer; - this.intlayer = intLayer; - } - - /** - * Create a new feature - * - * @param {paper.Point} point - * @memberof MultilevelPositionTool - */ - createNewFeature(point: paper.Point): void { - const featureIDs = []; - - // Set up flow layer component - const paramvalues = this.getCreationParameters(point); - let newFeature = Device.makeFeature(this.typeString, paramvalues); - this.currentFeatureID = newFeature.ID; - if (this.flowlayer !== null) { - this.viewManagerDelegate.addFeature(newFeature, this.viewManagerDelegate.renderLayers.indexOf(this.flowlayer)); - } - - featureIDs.push(newFeature.ID); - - const params_to_copy = newFeature.getParams(); - - let newtypestring; - const paramstoadd = newFeature.getParams(); - // Set up control layer component - if (ComponentAPI.library[this.typeString + "_control"]) { - newFeature.setParams(paramstoadd); - - this.currentFeatureID = newFeature.ID; - if (this.controllayer !== null) { - this.viewManagerDelegate.addFeature(newFeature, this.viewManagerDelegate.renderLayers.indexOf(this.controllayer)); - } - - featureIDs.push(newFeature.ID); - } - - // Set up integration layer component - if (ComponentAPI.library[this.typeString + "_integration"]) { - newtypestring = this.typeString + "_integration"; - newFeature = Device.makeFeature(newtypestring, paramvalues); - newFeature.setParams(paramstoadd); - - this.currentFeatureID = newFeature.ID; - if (this.intlayer !== null) { - this.viewManagerDelegate.addFeature(newFeature, this.viewManagerDelegate.renderLayers.indexOf(this.intlayer)); - } - - featureIDs.push(newFeature.ID); - } - - super.createNewComponent(this.typeString, params_to_copy, featureIDs); - this.viewManagerDelegate.saveDeviceState(); - } - - /** - * Show the target of the tool - * - * @returns {void} - * @memberof MultilevelPositionTool - */ - showTarget(): void { - if (this.lastPoint === null) { - return; - } - if (this.currentParameters === null) { - throw new Error("No parameters set"); - } - const target = PositionTool.getTarget(this.lastPoint); - this.viewManagerDelegate.updateTarget(this.typeString, this.setString, target, this.currentParameters); - } -} diff --git a/src/app/view/tools/panTool.ts b/src/app/view/tools/panTool.ts deleted file mode 100644 index aa6823ac..00000000 --- a/src/app/view/tools/panTool.ts +++ /dev/null @@ -1,69 +0,0 @@ -import MouseTool from "./mouseTool"; -import paper from "paper"; -import Registry from "../../core/registry"; -import SimpleQueue from "../../utils/simpleQueue"; -import ViewManager from "../viewManager"; - -export default class PanTool extends MouseTool { - startPoint: paper.Point | number[] | null; - lastPoint: paper.Point | number[] | null; - startCenter: paper.Point | number[] | null; - - updateQueue: SimpleQueue; - - dragging?: boolean; - - constructor(viewManager: ViewManager) { - super(viewManager); - this.startPoint = null; - this.lastPoint = null; - this.startCenter = null; - const ref = this; - this.updateQueue = new SimpleQueue(function () { - ref.pan(); - }, 10); - this.down = function (event) { - ref.startPan(MouseTool.getEventPosition(event as unknown as MouseEvent)!); - ref.showTarget(); - }; - this.up = function (event) { - ref.endPan(MouseTool.getEventPosition(event as unknown as MouseEvent)!); - ref.showTarget(); - }; - this.move = function (event) { - ref.moveHandler(MouseTool.getEventPosition(event as unknown as MouseEvent)!); - ref.showTarget(); - }; - } - - startPan(point: paper.Point): void { - this.dragging = true; - this.startPoint = point; - } - - moveHandler(point: paper.Point): void { - if (this.dragging) { - this.lastPoint = point; - this.updateQueue.run(); - // this.pan(); - } - } - - endPan(point: paper.Point): void { - this.pan(); - this.lastPoint = null; - this.dragging = false; - this.startPoint = null; - } - - showTarget(): void { - Registry.viewManager?.removeTarget(); - } - - pan(): void { - if (this.lastPoint) { - const delta = (this.lastPoint as paper.Point).subtract(this.startPoint as paper.Point); - Registry.viewManager?.moveCenter([delta.x, delta.y] as unknown as paper.Point); - } - } -} diff --git a/src/app/view/tools/positionTool.ts b/src/app/view/tools/positionTool.ts deleted file mode 100644 index 8c93346c..00000000 --- a/src/app/view/tools/positionTool.ts +++ /dev/null @@ -1,158 +0,0 @@ -import MouseTool from "./mouseTool"; - -import Registry from "../../core/registry"; -import Feature from "../../core/feature"; -import Device from "../../core/device"; -import SimpleQueue from "../../utils/simpleQueue"; - -import paper from "paper"; -import Params from "../../core/params"; -import Component from "../../core/component"; -import { ComponentAPI } from "@/componentAPI"; -import MapUtils from "../../utils/mapUtils"; -import ViewManager from "@/app/view/viewManager"; -import { Point } from "@/app/core/init"; - -export default class PositionTool extends MouseTool { - viewManagerDelegate: ViewManager; - typeString: string; - setString: string; - currentFeatureID: string | null; - currentParameters: { [k: string]: any } | null; - - lastPoint: Point = [0, 0]; - - showQueue: SimpleQueue; - - constructor(viewManagerDelegate: ViewManager, typeString: string, currentParameters: { [k: string]: any } | null = null) { - super(viewManagerDelegate); - this.viewManagerDelegate = viewManagerDelegate; - this.typeString = typeString; - this.setString = "Basic"; - this.currentFeatureID = null; - this.currentParameters = currentParameters; - const ref = this; - this.lastPoint = [0, 0]; - this.showQueue = new SimpleQueue( - function() { - ref.showTarget(); - }, - 20, - false - ); - this.up = function(event) { - // do nothing - }; - this.move = function(event) { - let point = MouseTool.getEventPosition((event as unknown) as MouseEvent); - if(point === null) { - return; - } - ref.lastPoint = [point.x, point.y]; - ref.showQueue.run(); - }; - this.down = function(event) { - ref.viewManagerDelegate.killParamsWindow(); - paper.project.deselectAll(); - ref.createNewFeature(MouseTool.getEventPosition((event as unknown) as MouseEvent)!); - }; - } - - createNewFeature(point: paper.Point): void { - const name = this.viewManagerDelegate.currentDevice?.generateNewName(this.typeString); - const newFeature = Device.makeFeature( - this.typeString, - { - position: PositionTool.getTarget([point.x, point.y]) - }, - name - ); - this.currentFeatureID = newFeature.ID; - this.viewManagerDelegate.addFeature(newFeature); - } - - /** - * Returns the 2D vector of the position of the cursor - * @param point - * @return {Point} - */ - static getTarget(point:Point): Point { - if (Registry.viewManager === null) { - throw new Error("View Manager is null"); - } - const target = Registry.viewManager.snapToGrid(point); - return target; - } - - static getMinTarget(point: Point): Point { - const target: Point = [Math.round(point[0]), Math.round(point[1])]; - return target; - } - - /** - * Renders the target - */ - showTarget(): void { - if (this.lastPoint === null) { - return; - } - const target = PositionTool.getTarget(this.lastPoint); - this.viewManagerDelegate.updateTarget(this.typeString, this.setString, target, this.currentParameters!); - } - - /** - * Creates a new component and adds it to the registry's current device - * Note: Takes the feature ids as an array - * TODO: Modify this to take the MINT String as another parameter - * @param typeString Type of the Feature - * @param params Map of all the paramters - * @param featureIDs [String] Feature id's of all the features that will be a part of this component - */ - createNewComponent(typeString: string, paramdata: { [k: string]: any }, featureIDs: string[]) { - const definition = ComponentAPI.getDefinition(typeString); - // Clean Param Data - const cleanparamdata: { [k: string]: any } = {}; - for (const key in paramdata) { - cleanparamdata[key] = paramdata[key].value; - } - cleanparamdata["position"] = [0, 0]; - const params = new Params(cleanparamdata, MapUtils.toMap(definition!.unique), MapUtils.toMap(definition!.heritable)); - const componentid = ComponentAPI.generateID(); - const name = Registry.currentDevice!.generateNewName(typeString); - const newComponent = new Component(params, name, definition!.mint, componentid); - let feature; - - for (const i in featureIDs) { - newComponent.addFeatureID(featureIDs[i]); - - // Update the component reference - feature = Registry.currentDevice!.getFeatureByID(featureIDs[i]); - feature.referenceID = componentid; - } - - newComponent.setInitialOffset(); - - newComponent.updateComponentPosition(paramdata["position"].value); - - this.viewManagerDelegate.currentDevice!.addComponent(newComponent); - return newComponent; - } - - deactivate(): void {} - - getCreationParameters(position: paper.Point) { - if (this.currentParameters === null) { - throw new Error("No parameters to create a new feature"); - } - const paramvalues = { - position: PositionTool.getTarget([position.x, position.y]) - }; - for (const i in this.currentParameters) { - const item = this.currentParameters[i]; - const param = item.name; - const value = item.value; - (paramvalues as any)[param] = value; - } - return paramvalues; - } -} diff --git a/src/app/view/tools/renderMouseTool.ts b/src/app/view/tools/renderMouseTool.ts deleted file mode 100644 index f652c503..00000000 --- a/src/app/view/tools/renderMouseTool.ts +++ /dev/null @@ -1,216 +0,0 @@ -// import RightClickMenu from "../ui/rightClickMenu"; -import MouseTool from "./mouseTool"; - -import Registry from "../../core/registry"; -import SimpleQueue from "../../utils/simpleQueue"; -import paper from "paper"; -import EventBus from "@/events/events"; -import { PaperView, ViewManager } from "@/app"; -import { ToolPaperObject } from "@/app/core/init"; - -// Mouse tool for use with uF Guide Tool -// Allows for selection only of nonphysical features - -export default class RenderMouseTool extends MouseTool { - paperView: PaperView; - dragging: boolean; - dragStart: paper.Point | null; - lastPoint: paper.Point | number[] | null; - - currentSelectBox: paper.Point | number[] | null; - currentSelection: any[]; - updateQueue: SimpleQueue; - - /** - * Creates an instance of RenderMouseTool. - * @param {ViewManager} viewManager - * @param {PaperView} paperview - * @memberof RenderMouseTool - */ - constructor(viewManager: ViewManager, paperview: PaperView) { - super(viewManager); - this.viewManagerDelegate = viewManager; - this.paperView = paperview; - this.dragging = false; - this.dragStart = null; - this.lastPoint = null; - this.currentSelectBox = null; - this.currentSelection = []; - const ref = this; - this.updateQueue = new SimpleQueue(function () { - ref.dragHandler(); - }, 20); - this.down = function (event) { - this.viewManagerDelegate.killParamsWindow(); - ref.mouseDownHandler(event as unknown as MouseEvent); - ref.dragging = true; - ref.showTarget(); - }; - this.move = function (event) { - if (ref.dragging) { - ref.lastPoint = MouseTool.getEventPosition(event as unknown as MouseEvent) as paper.Point; - ref.updateQueue.run(); - } - ref.showTarget(); - }; - this.up = function (event) { - ref.dragging = false; - ref.mouseUpHandler(MouseTool.getEventPosition(event as unknown as MouseEvent)!); - ref.showTarget(); - }; - } - - /** - * Handles the KeyDown event - * - * @param {KeyboardEvent} event - * @memberof RenderMouseTool - */ - keyHandler(event: KeyboardEvent): void {} - - /** - * Handles the drag event - * - * @memberof RenderMouseTool - */ - dragHandler(): void {} - - /** - * Shows the target - * - * @memberof RenderMouseTool - */ - showTarget(): void { - this.viewManagerDelegate.removeTarget(); - } - - /** - * Handles the mouse up event - * - * @param {paper.Point} point - * @memberof RenderMouseTool - */ - mouseUpHandler(point: paper.Point): void { - if (this.currentSelectBox) { - this.currentSelection = this.viewManagerDelegate.hitFeaturesWithViewElement(this.currentSelectBox); - // Figure out where this is even used - // this.selectFeatures(); - } - } - - /** - * Handles the mouse down event - * - * @param {MouseEvent} event - * @memberof RenderMouseTool - */ - mouseDownHandler(event: MouseEvent): void { - const point = MouseTool.getEventPosition(event); - const target = this.hitFeature(point!); - if (target) { - // if (this.viewManagerDelegate.getNonphysComponentForFeatureID(target.featureID) && this.viewManagerDelegate.getNonphysComponentForFeatureID(target.featureID).mint == "TEXT") { - const element = this.viewManagerDelegate.getNonphysElementFromFeatureID(target.featureID); - if (element && element.type == "Text") { - if (target.selected) { - const feat = this.viewManagerDelegate.getFeatureByID(target.featureID); - this.viewManagerDelegate.updateDefaultsFromFeature(feat); - // Check if the feature is a part of a component - if (feat.referenceID === null) { - throw new Error("ReferenceID of feature is null"); - } else { - if (element !== null) { - EventBus.get().emit(EventBus.DBL_CLICK_ELEMENT, event, element); - } else { - EventBus.get().emit(EventBus.DBL_CLICK_FEATURE, event, feat); - } - } - } else { - this.deselectFeatures(); - this.selectFeature(target); - } - } else { - this.deselectFeatures(); - } - } else { - this.deselectFeatures(); - } - } - - /** - * Function that is fired when we click to select a single object on the paperjs canvas - * - * @param {paper.Point} point - * @returns - * @memberof RenderMouseTool - */ - hitFeature(point: paper.Point) { - const target = this.viewManagerDelegate.view.hitFeature(point, true, true); - return target; - } - - /** - * Function that is fired when we click to select a single object on the paperjs canvas - * @param paperElement - */ - selectFeature(paperElement: any): void { - this.currentSelection.push(paperElement); - - // Find the component that owns this feature and then select all of the friends - const component = this.__getComponentWithFeatureID(paperElement.featureID); - if (component === null) { - // Does not belong to a component, hence this returns - paperElement.selected = true; - } else if (component !== null) { - // Belongs to the component so we basically select all features with this id - const featureIDs = component.featureIDs; - for (const i in featureIDs) { - const featureid = featureIDs[i]; - const actualfeature = this.viewManagerDelegate.view.paperFeatures[featureid]; - actualfeature.selected = true; - } - - this.viewManagerDelegate.view.selectedComponents.push(component); - } else { - throw new Error("Totally got the selection logic wrong, reimplement this"); - } - } - - /** - * Deselects all features - * - * @memberof RenderMouseTool - */ - deselectFeatures(): void { - this.paperView.clearSelectedItems(); - this.currentSelection = []; - } - - /** - * Finds and return the corresponding Component Object in the Registry's current device associated with - * the featureid. Returns null if no component is found. - * - * @param featureid - * @return {Component} - * @private - */ - __getComponentWithFeatureID(featureid: string) { - // Get component with the features - - const device_components = (this.viewManagerDelegate as any).nonphysComponents; - - // Check against every component - for (const i in device_components) { - const component = device_components[i]; - // Check against features in the in the component - const componentfeatures = component.featureIDs; - const index = componentfeatures.indexOf(featureid); - - if (index !== -1) { - // Found it !! - return component; - } - } - - return null; - } -} diff --git a/src/app/view/tools/selectTool.ts b/src/app/view/tools/selectTool.ts deleted file mode 100644 index dbca4c96..00000000 --- a/src/app/view/tools/selectTool.ts +++ /dev/null @@ -1,299 +0,0 @@ -import MouseTool, { MouseToolCallback } from "./mouseTool"; - -import Registry from "../../core/registry"; -import SimpleQueue from "../../utils/simpleQueue"; -import paper from "paper"; -import { ToolPaperObject } from "@/app/core/init"; -import ViewManager from "../viewManager"; - -export default class SelectTool extends MouseTool { - dragging: boolean; - dragStart: paper.Point | null; - lastPoint: paper.Point | null; - - currentSelectBox: any; - currentSelection: any[]; - - updateQueue: SimpleQueue; - - /** - * Creates an instance of SelectTool. - * @param {ViewManager} viewManagerDelegate - * @memberof SelectTool - */ - constructor(viewManagerDelegate: ViewManager) { - super(viewManagerDelegate); - this.dragging = false; - this.dragStart = null; - this.lastPoint = null; - this.currentSelectBox = null; - this.currentSelection = []; - const ref = this; - this.updateQueue = new SimpleQueue(function() { - ref.dragHandler(); - }, 20); - - this.down = function(event) { - Registry.viewManager?.killParamsWindow(); - ref.mouseDownHandler(event); - ref.dragging = true; - ref.showTarget(); - }; - - this.move = function(event) { - if (ref.dragging) { - ref.lastPoint = MouseTool.getEventPosition((event as unknown) as MouseEvent) as paper.Point; - ref.updateQueue.run(); - } - ref.showTarget(); - }; - - this.up = function(event) { - ref.dragging = false; - ref.mouseUpHandler(MouseTool.getEventPosition((event as unknown) as MouseEvent)!); - ref.showTarget(); - }; - } - - /** - * Handles the KeyDown event - * - * @param {KeyboardEvent} event - * @memberof SelectTool - */ - keyHandler(event: KeyboardEvent): void { - if (event.key === "delete" || event.key === "backspace") { - console.log("Removing feature"); - this.removeFeatures(); - } - if (event.key === "c") { - console.log("Detected a ctrlC"); - console.log(this.currentSelection); - } - } - - /** - * Handles the mouse drag event - * - * @memberof SelectTool - */ - dragHandler(): void { - if (this.dragStart) { - if (this.currentSelectBox) { - this.currentSelectBox.remove(); - } - this.currentSelectBox = this.rectSelect(this.dragStart, this.lastPoint!); - } - } - - /** - * Handles the mouse down event - * - * @memberof SelectTool - */ - showTarget(): void { - Registry.viewManager?.removeTarget(); - } - - /** - * Handles the mouse up event - * - * @param {paper.Point} point - * @memberof SelectTool - */ - mouseUpHandler(point: paper.Point): void { - if (this.currentSelectBox) { - this.currentSelection = Registry.viewManager!.hitFeaturesWithViewElement(this.currentSelectBox); - this.selectFeatures(); - } - this.killSelectBox(); - } - - - /** - * Deletes the selected features - * - * @memberof SelectTool - */ - removeFeatures(): void { - if (this.currentSelection.length > 0) { - for (let i = 0; i < this.currentSelection.length; i++) { - const paperFeature = this.currentSelection[i]; - let devicefeature = Registry.currentDevice!.getFeatureByID(paperFeature.featureID); - Registry.currentDevice!.removeFeature(devicefeature); - } - this.currentSelection = []; - //Registry.canvasManager!.render(); - } - } - - /** - * Handles the mouse down event - * - * @param {MouseEvent} event - * @memberof SelectTool - */ - mouseDownHandler(event: MouseEvent): void { - const point = MouseTool.getEventPosition((event as unknown) as MouseEvent); - const target = this.hitFeature(point!); - if (target) { - if (target.selected) { - const feat = Registry.currentDevice!.getFeatureByID(target.featureID); - Registry.viewManager!.updateDefaultsFromFeature(feat); - } else { - this.deselectFeatures(); - this.selectFeature(target); - } - } else { - this.deselectFeatures(); - this.dragStart = point!; - } - } - - /** - * Removes the selection box - * - * @memberof SelectTool - */ - killSelectBox(): void { - if (this.currentSelectBox) { - this.currentSelectBox.remove(); - this.currentSelectBox = null; - } - this.dragStart = null; - } - - - /** - * Helper method that tests if a point is within a rectangle - * - * @param {paper.Point} point - * @returns - * @memberof SelectTool - */ - hitFeature(point: paper.Point) { - const target = Registry.viewManager!.hitFeature((point as unknown) as number[]); - return target; - } - - /** - * Function that is fired when we click to select a single object on the paperjs canvas - * @param paperElement - */ - selectFeature(paperElement: any): void { - this.currentSelection.push(paperElement); - - // Find the component that owns this feature and then select all of the friends - const component = this.__getComponentWithFeatureID(paperElement.featureID); - if (component === null) { - // Does not belong to a component, hence this returns - paperElement.selected = true; - } else { - // Belongs to the component so we basically select all features with this id - const featureIDs = component.featureIDs; - for (const i in featureIDs) { - const featureid = featureIDs[i]; - const actualfeature = Registry.viewManager!.view.paperFeatures[featureid]; - actualfeature.selected = true; - } - - Registry.viewManager!.view.selectedComponents.push(component); - } - } - - /** - * Finds and return the corresponding Component Object in the Registry's current device associated with - * the featureid. Returns null if no component is found. - * - * @param featureid - * @return {Component} - * @private - */ - __getComponentWithFeatureID(featureid: string) { - // Get component with the features - - const device_components = Registry.currentDevice!.components; - - // Check against every component - for (const i in device_components) { - const component = device_components[i]; - // Check against features in the in the component - const componentfeatures = component.featureIDs; - const index = componentfeatures.indexOf(featureid); - - if (index !== -1) { - // Found it !! - console.log("Found Feature: " + featureid + " in component: " + component.id); - return component; - } - } - - return null; - } - - /** - * Function that is fired when we drag and select an area on the paperjs canvas - */ - selectFeatures(): void { - if (this.currentSelection) { - for (let i = 0; i < this.currentSelection.length; i++) { - const paperFeature = this.currentSelection[i]; - - // Find the component that owns this feature and then select all of the friends - const component = this.__getComponentWithFeatureID(paperFeature.featureID); - - if (component === null) { - // Does not belong to a component hence do the normal stuff - paperFeature.selected = true; - } else { - // Belongs to the component so we basically select all features with this id - const featureIDs = component.featureIDs; - for (const j in featureIDs) { - const featureid = featureIDs[j]; - const actualfeature = Registry.viewManager!.view.paperFeatures[featureid]; - actualfeature.selected = true; - } - - Registry.viewManager!.view.selectedComponents.push(component); - } - } - } - } - - /** - * Deselects all features - * - * @memberof SelectTool - */ - deselectFeatures(): void { - paper.project.deselectAll(); - this.currentSelection = []; - } - - /** - * Aborts the current operation - * - * @memberof SelectTool - */ - abort(): void { - this.deselectFeatures(); - this.killSelectBox(); - } - - /** - * Creates a selection box - * - * @param {paper.Point} point1 - * @param {paper.Point} point2 - * @returns - * @memberof SelectTool - */ - rectSelect(point1: paper.Point, point2: paper.Point) { - const rect = new paper.Path.Rectangle(point1, point2); - rect.fillColor = new paper.Color(0, 0.3, 1, 0.4); - rect.strokeColor = new paper.Color(0, 0, 0); - rect.strokeWidth = 2; - rect.selected = true; - return rect; - } -} diff --git a/src/app/view/tools/valveInsertionTool.ts b/src/app/view/tools/valveInsertionTool.ts deleted file mode 100644 index 5ec7ea99..00000000 --- a/src/app/view/tools/valveInsertionTool.ts +++ /dev/null @@ -1,276 +0,0 @@ -import MultilayerPositionTool from "./multilayerPositionTool"; - -import Registry from "../../core/registry"; -import Device from "../../core/device"; -import MouseTool, { MouseToolCallback } from "./mouseTool"; -import PositionTool from "./positionTool"; -import paper from "paper"; -import ViewManager from "@/app/view/viewManager"; -import Connection from "@/app/core/connection"; -import Component from "@/app/core/component"; -import { ValveType } from "@/app/core/init"; -import { ComponentAPI } from "@/componentAPI"; - -export default class ValveInsertionTool extends MultilayerPositionTool { - valveType: ValveType; - - /** - * Creates an instance of ValveInsertionTool. - * @param {ViewManager} viewManagerDelegate - * @param {string} mintstring - * @param {string} setString - * @param {{ [k: string]: any }} currentParameters - * @param {ValveType} [valveType=ValveType.NORMALLY_OPEN] - * @memberof ValveInsertionTool - */ - constructor(viewManagerDelegate: ViewManager, mintstring: string, setString: string, currentParameters: { [k: string]: any }, valveType: ValveType = ValveType.NORMALLY_OPEN) { - const threeduftype = ComponentAPI.getTypeForMINT(mintstring); - if (!threeduftype) { - throw new Error("Could not find type for MINT type " + mintstring); - } - super(viewManagerDelegate, threeduftype, setString, currentParameters); - this.valveType = valveType; - - const ref = this; - - this.down = function (event: MouseEvent) { - console.log(event); - const point = MouseTool.getEventPosition(event); - if (point === null) return; - const target = PositionTool.getTarget([point.x, point.y]); - // Check if connection exists at point - const connection = ref.checkIfConnectionExistsAt(new paper.Point(target[0], target[1])); - // if connection exists then place the valve - if (connection) { - ref.insertValve(point!, connection); - } else if ((event as any).ctrlKey || (event as any).metaKey) { - // Forced placement of the Valve - console.warn("Forcing placement of valve, a lot of things will not work correct if done this way"); - ref.forceInsertValve(point!); - } else { - // Send out error message - console.log("Could not find connection at this location"); - } - }; - } - - /** - * Places the component (single layer) - * @param point - * @param rotation - * @return {Component} - */ - createNewFeature(point: paper.Point, rotation: number | null = null): Component { - const featureIDs = []; - let overridedata; - - if (rotation) { - overridedata = { - position: PositionTool.getTarget([point.x, point.y]), - rotation: rotation - }; - } else { - overridedata = { - position: PositionTool.getTarget([point.x, point.y]) - }; - } - - const currentlevel = Math.floor(this.viewManagerDelegate!.renderLayers.indexOf(this.viewManagerDelegate.currentLayer) / 3); - // const flowlayer = currentlevel * 3; - const controllayer = currentlevel * 3 + 1; - // const intlayer = currentlevel * 3 + 2; - - const newFeature = Device.makeFeature(this.typeString, overridedata); - this.currentFeatureID = newFeature.ID; - - this.viewManagerDelegate.addFeature(newFeature, controllayer); - - featureIDs.push(newFeature.ID); - - const params_to_copy = newFeature.getParams(); - - const component = super.createNewComponent(this.typeString, params_to_copy, featureIDs); - - return component; - } - - /** - * Places the component (multi-layer) - * @param point - * @param rotation - * @return {Component} - */ - createNewMultiLayerFeature(point: paper.Point, rotation: number | null = null): Component { - const featureIDs = []; - let overridedata; - - if (rotation) { - overridedata = { - position: PositionTool.getTarget([point.x, point.y]), - rotation: rotation - }; - } else { - overridedata = { - position: PositionTool.getTarget([point.x, point.y]) - }; - } - - const currentlevel = Math.floor(Registry.viewManager!.renderLayers.indexOf(this.viewManagerDelegate.currentLayer) / 3); - const flowlayer = currentlevel * 3; - const controllayer = currentlevel * 3 + 1; - - let newFeature = Device.makeFeature(this.typeString, overridedata); - this.currentFeatureID = newFeature.ID; - this.viewManagerDelegate.addFeature(newFeature, flowlayer); - - featureIDs.push(newFeature.ID); - - const params_to_copy = newFeature.getParams(); - - const newtypestring = this.typeString + "_control"; - const paramstoadd = newFeature.getParams(); - newFeature = Device.makeFeature(newtypestring, overridedata); - newFeature.setParams(paramstoadd); - - this.currentFeatureID = newFeature.ID; - this.viewManagerDelegate.addFeature(newFeature, controllayer); - - featureIDs.push(newFeature.ID); - - const component = super.createNewComponent(this.typeString, params_to_copy, featureIDs); - - return component; - } - - /** - * Shows the target - */ - showTarget(): void { - if (this.lastPoint === null) { - return; - } - const target = PositionTool.getTarget(this.lastPoint); - this.viewManagerDelegate.updateTarget(this.typeString, this.setString, target, this.currentParameters!); - } - - /** - * Checks if the connection exists at the point where the user clicks - * @param target - * @return {*} - */ - checkIfConnectionExistsAt(target: paper.Point): Connection | null { - const hit = Registry.viewManager!.view.hitFeature(target, false); - // TODO: check if the hit feature belongs to a connection - if (hit) { - const connection = Registry.currentDevice!.getConnectionForFeatureID(hit.featureID); - return connection; - } - - return null; - } - - /** - * Inserts the valve at the point on the connection - * @param point - * @param connection - */ - insertValve(point: paper.Point, connection: Connection): void { - let angle = this.__getRotation(point, connection); - if (angle < 0) { - angle += 180; - } - - let component: Component; - - // TODO: Enable this.is3D functionality - if (this.valveType === ValveType.NORMALLY_OPEN) { - component = this.createNewFeature(point, angle); - this.viewManagerDelegate.currentDevice!.insertValve(component, connection, this.valveType); - } else if (this.valveType === ValveType.NORMALLY_CLOSED) { - angle += 90; - component = this.createNewMultiLayerFeature(point, angle); - this.viewManagerDelegate.currentDevice!.insertValve(component, connection, this.valveType); - } - // Registry.viewManager!.updatesConnectionRender(connection); - Registry.viewManager!.saveDeviceState(); - } - - /** - * Inserts the valve at the point on the connection - * @param point - * @param connection - */ - forceInsertValve(point: paper.Point): void { - let component; - if (this.typeString == "Valve3D") { - // TODO: Insert the valve features in both flow and control - component = this.createNewMultiLayerFeature(point); - // TODO: Redraw the connection - } else { - // TODO: Insert the valve feature in flow - component = this.createNewFeature(point); - } - - Registry.viewManager!.saveDeviceState(); - } - - /** - * Generates the rotation for the valve when placed on the connection - * @param point - * @param connection - * @return {*} - * @private - */ - __getRotation(point: paper.Point, connection: Connection) { - // Find closes normal intersection of the point and place the - let conn_waypoints; - let lowestdist = 1000000000000000000000; - let p0: number[], p1: number[], sol: number; - const paths = connection.getPaths(); - const waypoints = []; - for (const j in paths) { - conn_waypoints = paths[j]; - // conn_waypoints = connection.getValue("wayPoints"); - for (let i = 0; i < conn_waypoints.length; i++) { - waypoints.push(conn_waypoints[i]); - } - - // Find out which segment the point is on - for (let i = 0; i < waypoints.length - 1; i++) { - p0 = waypoints[i]; - p1 = waypoints[i + 1]; - - const tempdist = this.__calculateNormalDistance(point, p0, p1); - if (tempdist < lowestdist || i === 0) { - sol = i; - lowestdist = tempdist; - } - } - - p0 = waypoints[sol!]; - p1 = waypoints[sol! + 1]; - } - // waypoints.splice(0, 0, connection.getValue("start")); - - const to = new paper.Point(p0![0], p0![1]); - const from = new paper.Point(p1![0], p1![1]); - const vec = from.subtract(to); - - return vec.angle; - } - - /** - * Calculates normal distance - * @param point - * @param p0 - * @param p1 - * @private - */ - __calculateNormalDistance(point: paper.Point, p0: number[], p1: number[]) { - const line = new paper.Path.Line(new paper.Point(p0[0], p0[1]), new paper.Point(p1[0], p1[1])); - const target = new paper.Point(point.x, point.y); - const closestpt = line.getNearestPoint(target); - const dist = closestpt.getDistance(point); - return dist; - } -} diff --git a/src/app/view/uiElement.ts b/src/app/view/uiElement.ts deleted file mode 100644 index 4645a22f..00000000 --- a/src/app/view/uiElement.ts +++ /dev/null @@ -1,48 +0,0 @@ -import Parameter from "../core/parameter"; -import { ComponentAPI } from "@/componentAPI"; - -export default class UIElement { - protected __type: string; - protected __position: [number, number]; - protected __height: number; - protected __featureIDs: Array; - protected __id: string; - - //constructor(type: string, paramdata: { [index: string]: Parameter }, featureIDs: Array, id: string = ComponentAPI.generateID()) { - constructor(id: string = ComponentAPI.generateID()) { - this.__position = [0, 0]; - this.__height = 0; - this.__type = "BlankUIElement"; - this.__featureIDs = []; - // this.__position = paramdata.position.value; - // this.__height = paramdata.height.value; - // this.__type = type; - // this.__featureIDs = featureIDs; - this.__id = id; - } - - get type(): string { - return this.__type; - } - - get featureIDs(): Array { - return this.__featureIDs; - } - - get position(): [number, number] { - return this.__position; - } - - get id(): string { - return this.__id; - } - - hasFeatureID(featureID: string): boolean { - if (this.__featureIDs.includes(featureID)) return true; - else return false; - } - - draw(): void { - console.log(`Drawing at ${this.__position[0]}, ${this.__position[1]}`); - } -} diff --git a/src/app/view/viewManager.ts b/src/app/view/viewManager.ts deleted file mode 100644 index 39979ab0..00000000 --- a/src/app/view/viewManager.ts +++ /dev/null @@ -1,1785 +0,0 @@ -// import ZoomToolBar from "@/components/zoomSlider.vue"; -import paper from "paper"; - -import Registry from "../core/registry"; -import * as Colors from "./colors"; -import { saveAs } from "file-saver"; - -import Device from "../core/device"; -import SelectTool from "./tools/selectTool"; -import InsertTextTool from "./tools/insertTextTool"; -import SimpleQueue from "../utils/simpleQueue"; -import MouseSelectTool from "./tools/mouseSelectTool"; -// import RenderMouseTool from "./tools/renderMouseTool"; - -import DXFObject from "../core/dxfObject"; -import EdgeFeature from "../core/edgeFeature"; -import * as HTMLUtils from "../utils/htmlUtils"; -import MouseAndKeyboardHandler from "./mouseAndKeyboardHandler"; -import DesignHistory from "./designHistory"; -import MoveTool from "./tools/moveTool"; -import ComponentPositionTool from "./tools/componentPositionTool"; -import MultilayerPositionTool from "./tools/multilayerPositionTool"; -import MultilevelPositionTool from "./tools/multilevelPositionTool"; -import CellPositionTool from "./tools/cellPositionTool"; -import ValveInsertionTool from "./tools/valveInsertionTool"; -import PositionTool from "./tools/positionTool"; -import ConnectionTool from "./tools/connectionTool"; -import GenerateArrayTool from "./tools/generateArrayTool"; -import CustomComponentManager from "./customComponentManager"; -import CustomComponentPositionTool from "./tools/customComponentPositionTool"; -import { setButtonColor } from "../utils/htmlUtils"; -import PaperView from "./paperView"; -import AdaptiveGrid from "./grid/adaptiveGrid"; -import DAFDPlugin from "../plugin/dafdPlugin"; -import { Examples } from "../index"; -import Feature from "../core/feature"; -import Layer from "../core/layer"; -import Component from "../core/component"; -import EventBus from "@/events/events"; -import { ComponentAPI } from "@/componentAPI"; -import RenderLayer from "@/app/view/renderLayer"; - -import LoadUtils from "@/app/utils/loadUtils"; -import ExportUtils, { SerializationError } from "@/app/utils/exportUtils"; -import { LogicalLayerType, InterchangeV1_2, ValveType } from "@/app/core/init"; - -import { Point } from "@/app/core/init"; - -/** - * View manager class - */ -import { MultiplyOperation } from "three"; -import UIElement from "./uiElement"; -import Connection from "../core/connection"; -import Params from "../core/params"; -import MouseTool from "./tools/mouseTool"; -import { generateRenderLayers } from "../utils/renderUtils"; - -export default class ViewManager { - view: PaperView; - renderLayers: RenderLayer[]; - activeRenderLayerIndex: number; - nonphysElements: UIElement[]; - tools: { [k: string]: any }; - rightMouseTool: MouseTool; - updateQueue: any; - saveQueue: any; - undoStack: any; - pasteboard: any[]; - mouseAndKeyboardHandler: MouseAndKeyboardHandler; - minZoom: number; - maxZoom: number; - threeD: boolean; - renderer: any; - - messageBox?: any; - customComponentManager?: CustomComponentManager; - currentSelection?: any; - - private __grid: AdaptiveGrid; - private __currentDevice: Device | null; - private __button2D?: HTMLButtonElement; - private __button3D?: HTMLButtonElement; - private __canvasBlock?: HTMLCanvasElement; - private __renderBlock?: HTMLCanvasElement; - - // TODO : Check if we can remove this tracking - currentLayer: RenderLayer; - - /** - * Default ViewManger Constructor - */ - constructor() { - this.view = new PaperView("c", this); - this.__grid = new AdaptiveGrid(this); - Registry.currentGrid = this.__grid; - this.renderLayers = []; - this.nonphysElements = []; // TODO - Keep track of what types of objects fall here UIElements - this.tools = {}; - this.rightMouseTool = new SelectTool(this); - this.__currentDevice = null; - const reference = this; - this.updateQueue = new SimpleQueue(function() { - reference.view.refresh(); - }, 20); - - this.saveQueue = new SimpleQueue(function() { - reference.saveToStorage(); - }); - - this.undoStack = new DesignHistory(); - this.pasteboard = []; - - this.mouseAndKeyboardHandler = new MouseAndKeyboardHandler(this); - - this.view.setResizeFunction(function() { - reference.updateGrid(); - reference.updateAlignmentMarks(); - - reference.view.updateRatsNest(); - reference.view.updateComponentPortsRender(); - reference.updateDevice(Registry.currentDevice!); - }); - - const func = function(event: any) { - reference.adjustZoom(event.deltaY, (reference.getEventPosition(event) as unknown) as number[]); - }; - - // this.manufacturingPanel = new ManufacturingPanel(this); - - // this.exportPanel = new ExportPanel(this); - - this.view.setMouseWheelFunction(func); - this.minZoom = 0.0001; - this.maxZoom = 5; - this.setupTools(); - const ref = this; - EventBus.get().on(EventBus.UPDATE_RENDERS, function(feature, refresh = true) { - if (ref.ensureFeatureExists(feature)) { - ref.view.updateFeature(feature); - ref.refresh(refresh); - } - }); - - // TODO: Figure out how remove UpdateQueue as dependency mechanism - this.__grid.setColor(Colors.BLUE_500); - - // Removed from Page Setup - this.threeD = false; - this.renderer = Registry.threeRenderer; - // this.__button2D = document.getElementById("button_2D"); - // this.__canvasBlock = document.getElementById("canvas_block"); - // this.__renderBlock = document.getElementById("renderContainer"); - // this.setupDragAndDropLoad("#c"); - // this.setupDragAndDropLoad("#renderContainer"); - this.currentLayer = this.renderLayers[0]; - this.activeRenderLayerIndex = 0; - - } - - - /** - * Returns the current device the ViewManager is displaying. Right now I'm using this to replace the - * Registry.currentDevice dependency, however this might change as the modularity requirements change. - * - * @return {Device} - * @memberof ViewManager - */ - get currentDevice(): Device | null { - return this.__currentDevice; - } - - /** - * Initiates the copy operation on the selected feature - * @returns {void} - * @memberof ViewManager - */ - initiateCopy(): void { - const selectedFeatures = this.view.getSelectedFeatures(); - if (selectedFeatures.length > 0) { - this.pasteboard[0] = selectedFeatures[0]; - } - } - - /** - * Initiating the zoom toolbar - * @memberof ViewManager - * @returns {void} - */ - setupToolBars(): void { - // Initiating the zoom toolbar - // this.zoomToolBar = new ZoomToolBar(0.0001, 5); - // this.componentToolBar = new ComponentToolBar(this); - this.resetToDefaultTool(); - } - - /** - * Sets the initial state of the name map - * @memberof ViewManager - * @returns {void} - */ - setNameMap(): void { - const newMap = new Map(); - for (let i = 0; i < this.currentDevice!.layers.length; i++) { - const [nameStr, nameNum] = this.currentDevice!.layers[i].name.split("_"); - if (newMap.has(nameStr)) { - if (newMap.get(nameStr) < nameNum) newMap.set(nameStr, parseInt(nameNum)); - } else { - newMap.set(nameStr, parseInt(nameNum)); - } - } - for (let i = 0; i < this.currentDevice!.connections.length; i++) { - const [nameStr, nameNum] = this.currentDevice!.connections[i].name.split("_"); - if (newMap.has(nameStr)) { - if (newMap.get(nameStr) < nameNum) newMap.set(nameStr, parseInt(nameNum)); - } else { - newMap.set(nameStr, parseInt(nameNum)); - } - } - for (let i = 0; i < this.currentDevice!.components.length; i++) { - const [nameStr, nameNum] = this.currentDevice!.components[i].name.split("_"); - if (newMap.has(nameStr)) { - if (newMap.get(nameStr) < nameNum) newMap.set(nameStr, parseInt(nameNum)); - } else { - newMap.set(nameStr, parseInt(nameNum)); - } - } - for (let i = 0; i < this.renderLayers.length; i++) { - const [nameStr, nameNum] = this.renderLayers[i].name.split("_"); - if (newMap.has(nameStr)) { - if (newMap.get(nameStr) < nameNum) newMap.set(nameStr, parseInt(nameNum)); - } else { - newMap.set(nameStr, parseInt(nameNum)); - } - } - - this.currentDevice!.nameMap = newMap; - } - - /** - * Adds a device to the view manager - * @param {Device} device Device to be added - * @param {Boolean} refresh Default true - * @memberof ViewManager - * @returns {void} - */ - addDevice(device: Device, refresh = true): void { - this.view.addDevice(device); - this.__addAllDeviceLayers(device, false); - this.refresh(refresh); - } - - /** - * Adds all the layers in the device - * @param {Device} device Selected device - * @param {boolean} refresh Whether to refresh or not. true by default - * @memberof ViewManager - * @returns {void} - * @private - */ - __addAllDeviceLayers(device: Device, refresh = true): void { - for (let i = 0; i < device.layers.length; i++) { - const layer = device.layers[i]; - this.addLayer(layer, i, false); - } - } - - /** - * Removes all layers in the device - * @param {Device} device Selected device - * @param {boolean} refresh Whether to refresh or not. true by default - * @memberof ViewManager - * @returns {void} - */ - __removeAllDeviceLayers(device: Device, refresh = true): void { - for (let i = 0; i < device.layers.length; i++) { - const layer = device.layers[i]; - this.removeLayer(layer, i, false); - } - } - - /** - * Removes the device from the view - * @param {Device} device Selected device to remove - * @param {Boolean} refresh Whether to refresh or not. true by default - * @returns {void} - * @memberof ViewManager - */ - removeDevice(device: Device, refresh = true): void { - this.view.removeDevice(); - this.__removeAllDeviceLayers(device, false); - this.refresh(refresh); - } - - /** - * Updates the device in the view - * @param {Device} device Selected device to update - * @param {boolean} refresh Whether to refresh or not. true by default - * @returns {void} - * @memberof ViewManager - */ - updateDevice(device: Device, refresh = true): void { - this.view.updateDevice(device); - this.refresh(refresh); - } - - /** - * Adds a feature to the view - * @param {Feature} feature Feature to add - * @param {Boolean} refresh Whether to refresh or not. true by default - * @returns {void} - * @memberof ViewManager - */ - addFeature(feature: Feature, index = this.activeRenderLayerIndex, isPhysicalFlag = true, refresh = true): void { - // let isPhysicalFlag = true; - this.renderLayers[index as number].addFeature(feature, isPhysicalFlag); - if (this.ensureFeatureExists(feature)) { - this.view.addFeature(feature); - this.refresh(refresh); - } - } - - /** - * Returns the component identified by the id - * @param {string} id ID of the feature to get the component - * @return {UIElement|null} - * @memberof ViewManager - */ - getNonphysElementFromFeatureID(id: string): UIElement | null { - for (const i in this.nonphysElements) { - const element = this.nonphysElements[i]; - // go through each component's features - for (const j in element.featureIDs) { - if (element.featureIDs[j] === id) { - return element; - } - } - } - - return null; - } - - /** - * Updates a feature from the view - * @param {Feature} feature Feature to update - * @param {boolean} refresh Whether to refresh or not. true by default - * @returns {void} - * @memberof ViewManager - */ - updateFeature(feature: Feature, refresh = true): void { - if (this.ensureFeatureExists(feature)) { - this.view.updateFeature(feature); - this.refresh(refresh); - } - } - - /** - * Removes feature from the view - * @param {Feature} feature Feature to remove - * @param {boolean} refresh Whether to refresh or not. true by default - * @returns {void} - * @memberof ViewManager - */ - removeFeature(feature: Feature, refresh = true): void { - const layer = this.getRenderLayerByID(feature.ID); - if (this.ensureFeatureExists(feature)) { - this.view.removeFeature(feature); - this.refresh(refresh); - } - layer.removeFeatureByID(feature.ID); - } - - /** - * Removes feature from the view - * @param {string} feature Feature to remove - * @param {boolean} refresh Whether to refresh or not. true by default - * @returns {void} - * @memberof ViewManager - */ - removeFeatureByID(featureID: string, refresh = true): void { - const layer = this.getRenderLayerByID(featureID); - const feature = layer.getFeature(featureID); - if (this.ensureFeatureExists(feature)) { - this.view.removeFeature(feature); - this.refresh(refresh); - } - layer.removeFeatureByID(featureID); - } - - /** - * Adds layer to the view - * @param {Layer} layer Layer to add - * @param {Number} index Index of the layer - * @param {Boolean} refresh Whether to refresh or not. true by default - * @returns {void} - * @memberof ViewManager - */ - addLayer(layer: Layer, index: number, refresh = true): void { - if (this.__isLayerInCurrentDevice(layer)) { - this.view.addLayer(layer, index); - this.__addAllLayerFeatures(layer, index, false); - this.refresh(refresh); - } - } - - /** - * Create a new set of layers (flow, control and cell) for the upcoming level. - * @returns {void} - * @memberof ViewManager - */ - createNewLayerBlock(): void { - if(this.__currentDevice === null) { - throw new Error("No device set on ViewManager"); - } - // Generate model layers - let groupNum = this.__currentDevice.layers.length; - if (groupNum != 0) groupNum = groupNum / 3; - - const newlayers = []; - newlayers[0] = new Layer({ z_offset: 0, flip: false }, this.currentDevice?.generateNewName("LayerFlow"), LogicalLayerType.FLOW, groupNum.toString()); - newlayers[1] = new Layer({ z_offset: 0, flip: false }, this.currentDevice?.generateNewName("LayerControl"), LogicalLayerType.CONTROL, groupNum.toString()); - newlayers[2] = new Layer({ z_offset: 0, flip: false }, this.currentDevice?.generateNewName("LayerIntegration"), LogicalLayerType.INTEGRATION, groupNum.toString()); - // Add model layers to current device - this.__currentDevice.createNewLayerBlock(newlayers); - - // Find all the edge features - const edgefeatures = []; - const devicefeatures = Registry.currentDevice?.layers[0].features; - let feature; - - for (const i in devicefeatures) { - feature = devicefeatures[i]; - if (feature.fabType === "EDGE") { - edgefeatures.push(feature); - } - } - - // Add the Edge Features from layer '0' - // to all other layers - for (const i in newlayers) { - for (const j in edgefeatures) { - newlayers[i].addFeature(edgefeatures[j]); - } - } - - // Added the new layers - for (const i in newlayers) { - const layertoadd = newlayers[i]; - const index = this.view.paperLayers.length; - this.addLayer(layertoadd, index, true); - } - - // Add new renderLayers - this.renderLayers[this.renderLayers.length] = new RenderLayer(this.currentDevice?.generateNewName("RenderLayerFlow"), newlayers[0], LogicalLayerType.FLOW); - this.renderLayers[this.renderLayers.length] = new RenderLayer(this.currentDevice?.generateNewName("RenderLayerControl"), newlayers[1], LogicalLayerType.CONTROL); - this.renderLayers[this.renderLayers.length] = new RenderLayer(this.currentDevice?.generateNewName("RenderLayerIntegration"), newlayers[2], LogicalLayerType.INTEGRATION); - for (const i in edgefeatures) { - this.renderLayers[this.renderLayers.length - 3].addFeature(edgefeatures[i]); - this.renderLayers[this.renderLayers.length - 2].addFeature(edgefeatures[i]); - this.renderLayers[this.renderLayers.length - 1].addFeature(edgefeatures[i]); - } - - console.log("Active Layer", this.activeRenderLayerIndex); - this.setActiveRenderLayer(this.renderLayers.length - 3); - } - - /** - * Deletes the layers at the level index, we have 3-set of layers so it deletes everything at - * that level - * @param {number} levelindex Integer only - * @returns {void} - * @memberof ViewManager - */ - deleteLayerBlock(levelindex: number): void { - // Delete the levels in the device model - Registry.currentDevice?.deleteLayer(levelindex * 3); - Registry.currentDevice?.deleteLayer(levelindex * 3); - Registry.currentDevice?.deleteLayer(levelindex * 3); - - // Delete levels in render model - this.renderLayers.splice(levelindex * 3, 3); - if (this.activeRenderLayerIndex! > levelindex * 3 + 2) { - this.setActiveRenderLayer(this.activeRenderLayerIndex! - 3); - } else if (this.activeRenderLayerIndex! < levelindex * 3) { - console.log("No change"); - } else { - if (levelindex == 0) { - if (this.renderLayers.length == 0) { - // The param shouldn't be null - this.setActiveRenderLayer(levelindex); - } else { - this.setActiveRenderLayer(0); - } - } else { - this.setActiveRenderLayer((levelindex - 1) * 3); - } - } - - // Delete the levels in the render model - this.view.removeLayer(levelindex * 3); - this.view.removeLayer(levelindex * 3); - this.view.removeLayer(levelindex * 3); - this.updateActiveLayer(); - this.refresh(); - } - - setActiveRenderLayer(index: number): void { - this.activeRenderLayerIndex = index; - this.currentLayer = this.renderLayers[index]; // Registry.currentDevice.layers[index]; - this.updateActiveLayer(); - } - - /** - * Removes layer from the view - * @param {Layer} layer Layer to be removed from the view - * @param {Number} index Index of the layer to remove - * @param {Boolean} refresh Default to true - * @returns {view} - * @memberof ViewManager - */ - removeLayer(layer: Layer, index: number, refresh = true): void { - if (this.__isLayerInCurrentDevice(layer)) { - this.view.removeLayer(index); - this.__removeAllLayerFeatures(layer); - this.refresh(refresh); - } - } - - /** - * Converts the layers to SVG format - * @returns {} - * @memberof ViewManager - */ - layersToSVGStrings() { - return this.view.layersToSVGStrings(); - } - - /** - * Adds all the features of the layer - * @param {Layer} layer Selected layer - * @param {Boolean} refresh Default to true - * @returns {void} - * @memberof ViewManager - * @private - */ - __addAllLayerFeatures(layer: Layer, index: number, refresh = true): void { - for (const key in layer.features) { - const feature = layer.features[key]; - this.addFeature(feature, index, false); - this.refresh(refresh); - } - } - - /** - * Updates all the feature of the layer - * @param {Layer} layer Selected layer - * @param {boolean} refresh Whether to refresh or not. true by default - * @returns {void} - * @memberof ViewManager - */ - __updateAllLayerFeatures(layer: Layer, refresh = true): void { - for (const key in layer.features) { - const feature = layer.features[key]; - this.updateFeature(feature, false); - this.refresh(refresh); - } - } - - /** - * Removes all feature of the layer - * @param {Layer} layer Selected layer - * @param {Boolean} refresh Whether to refresh or not. true by default - * @returns {void} - * @memberof ViewManager - */ - __removeAllLayerFeatures(layer: Layer, refresh = true): void { - for (const key in layer.features) { - const feature = layer.features[key]; - this.removeFeature(feature, false); - this.refresh(refresh); - } - } - - /** - * Updates layer - * @param {Layer} layer Selected layer to be updated - * @param {boolean} refresh Whether to refresh or not. true by default - * @returns {void} - * @memberof ViewManager - */ - updateLayer(layer: Layer, refresh = true): void { - if (this.__isLayerInCurrentDevice(layer)) { - // Missing param - this.refresh(refresh); - } - } - - /** - * Updates the active layer - * @param {Boolean} refresh Default to true - * @returns {void} - * @memberof ViewManager - */ - updateActiveLayer(refresh = true): void { - if(this.activeRenderLayerIndex === null){ - console.warn("Attempting update active layer in view manager with no active layer value"); - return; - } - this.view.setActiveLayer(this.activeRenderLayerIndex as number); - this.refresh(refresh); - } - - /** - * Removes the grid - * @param {Boolean} refresh Default to true - * @returns {void} - * @memberof ViewManager - */ - removeGrid(refresh = true): void { - if (this.__hasCurrentGrid()) { - this.view.removeGrid(); - this.refresh(refresh); - } - } - - /** - * Update grid - * @param {Boolean} refresh Default to true - * @returns {void} - * @memberof ViewManager - */ - updateGrid(refresh = true): void { - if (this.__hasCurrentGrid()) { - this.view.updateGrid(Registry.currentGrid); - this.refresh(refresh); - // Send the EventBus Notification - EventBus.get().emit(EventBus.UPDATE_GRID_SIZE); - } - } - - /** - * Update the alignment marks of the view - * @returns {void} - * @memberof ViewManager - */ - updateAlignmentMarks(): void { - this.view.updateAlignmentMarks(); - } - - /** - * Clear the view - * @returns {void} - * @memberof ViewManager - */ - clear(): void { - this.view.clear(); - } - - /** - * Sets a specific value of zoom - * @param {Number} zoom Zoom value - * @param {boolean} refresh Whether it will refresh or not. true by default - * @returns {void} - * @memberof ViewManager - */ - setZoom(zoom: number, refresh = true): void { - if (zoom > this.maxZoom) zoom = this.maxZoom; - else if (zoom < this.minZoom) zoom = this.minZoom; - this.view.setZoom(zoom); - this.updateGrid(false); - this.updateAlignmentMarks(); - this.view.updateRatsNest(); - this.view.updateComponentPortsRender(); - - this.updateDevice(Registry.currentDevice!, false); - this.__updateViewTarget(false); - this.refresh(refresh); - } - - /** - * Automatically generates a rectangular border for the device - * @returns {void} - * @memberof ViewManager - */ - generateBorder(): void { - const borderfeature = new EdgeFeature(null, new Params({}, new Map(), new Map())); - - // Get the bounds for the border feature and then update the device dimensions - const xspan = Registry.currentDevice?.getXSpan(); - const yspan = Registry.currentDevice?.getYSpan(); - borderfeature.generateRectEdge(xspan as number, yspan as number); - - // Adding the feature to all the layers - for (const i in Registry.currentDevice!.layers) { - const layer = Registry.currentDevice!.layers[i]; - layer.addFeature(borderfeature); - } - } - - /** - * Accepts a DXF object and then converts it into a feature, an edgeFeature in particular - * @param dxfobject - * @returns {void} - * @memberof ViewManager - */ - importBorder(dxfobject: any): void { - const customborderfeature = new EdgeFeature(null, new Params({}, new Map(), new Map())); - for (const i in dxfobject.entities) { - const foo = new DXFObject(dxfobject.entities[i]); - customborderfeature.addDXFObject(foo); - } - - // Adding the feature to all the layers - if(Registry.currentDevice === null) { - throw new Error("No device selected"); - } - for (const i in Registry.currentDevice.layers) { - const layer = Registry.currentDevice.layers[i]; - layer.addFeature(customborderfeature); - } - - // Get the bounds for the border feature and then update the device dimensions - const bounds = this.view.getRenderedFeature(customborderfeature.ID).bounds; - - Registry.currentDevice?.setXSpan(bounds.width); - Registry.currentDevice?.setYSpan(bounds.height); - // Refresh the view - Registry.viewManager?.view.initializeView(); - Registry.viewManager?.view.refresh(); - } - - /** - * Deletes the border - * @returns {void} - * @memberof ViewManager - */ - deleteBorder(): void { - /* - 1. Find all the features that are EDGE type - 2. Delete all these features - */ - - console.log("Deleting border..."); - - const features = Registry.currentDevice?.getAllFeaturesFromDevice(); - console.log("All features", features); - - const edgefeatures = []; - if (features === undefined){ - throw new Error("No features found"); - } - for (const i in features) { - // Check if the feature is EDGE or not - if (features[i].fabType === "EDGE") { - edgefeatures.push(features[i]); - } - } - - // Delete all the features - for (const i in edgefeatures) { - this.removeFeatureByID(edgefeatures[i].ID); - } - - console.log("Edgefeatures", edgefeatures); - } - - /** - * Removes the target view - * @memberof ViewManager - * @returns {void} - */ - removeTarget(): void { - this.view.removeTarget(); - } - - /** - * Update the target view - * @param {string} featureType - * @param {string} featureSet - * @param {Array} position Array with X and Y coordinates - * @param {boolean} refresh Whether to refresh or not. true by default - * @returns {void} - * @memberof ViewManager - */ - updateTarget(featureType: string, featureSet: string, position: Point, currentParameters: { [k: string]: any } | null = null, refresh = true): void { - this.view.addTarget(featureType, featureSet, position, currentParameters); - this.view.updateAlignmentMarks(); - this.view.updateRatsNest(); - this.refresh(refresh); - } - - /** - * Update the view target - * @param {Boolean} refresh Default to true - * @returns {void} - * @memberof ViewManager - */ - __updateViewTarget(refresh = true): void { - this.view.updateTarget(); - this.updateAlignmentMarks(); - this.view.updateRatsNest(); - this.view.updateComponentPortsRender(); - this.refresh(refresh); - } - - /** - * Adjust the zoom value in a certain point - * @param {Number} delta Value of zoom - * @param {Array} point Coordinates to zoom in - * @param {Boolean} refresh Default to true - * @returns {void} - * @memberof ViewManager - */ - adjustZoom(delta: number, point: number[], refresh = true): void { - const belowMin = this.view.getZoom() >= this.maxZoom && delta < 0; - const aboveMax = this.view.getZoom() <= this.minZoom && delta > 0; - if (!aboveMax && !belowMin) { - this.view.adjustZoom(delta, new paper.Point(point)); - this.updateGrid(false); - // this.updateAlignmentMarks(); - this.view.updateRatsNest(); - this.view.updateComponentPortsRender(); - this.updateDevice(Registry.currentDevice!, false); - this.__updateViewTarget(false); - } else { - // console.log("Too big or too small!"); - } - this.refresh(refresh); - } - - /** - * Sets the center value - * @param {Array} center Center coordinates - * @param {Boolean} refresh Default to true - * @returns {void} - * @memberof ViewManager - */ - setCenter(center: number[], refresh = true): void { - this.view.setCenter((center as unknown) as paper.Point); - this.updateGrid(false); - // this.updateAlighmentMarks(); - - this.updateDevice(Registry.currentDevice!, false); - this.refresh(refresh); - } - - /** - * Moves center by a certain value - * @param {number} delta - * @param {boolean} refresh Whether to refresh or not. true by default - * @returns {void} - * @memberof ViewManager - */ - moveCenter(delta: paper.Point, refresh = true): void { - this.view.moveCenter(delta); - this.updateGrid(false); - // this.updateAlignmentMarks(); - this.view.updateRatsNest(); - this.view.updateComponentPortsRender(); - this.updateDevice(Registry.currentDevice!, false); - this.refresh(refresh); - } - - /** - * Save the device to JSON format - * @returns {void} - * @memberof ViewManager - */ - saveToStorage(): void { - if (Registry.viewManager) { - try { - localStorage.setItem("currentDevice", JSON.stringify(Registry.viewManager.generateExportJSON())); - } catch (err) { - // can't save, so.. don't? - } - } - } - - /** - * Refresh the view - * @param {boolean} refresh Whether to refresh or not. true by default - * @returns {void} - * @memberof ViewManager - */ - refresh(refresh = true): void { - this.updateQueue.run(); - // Update the toolbar - const spacing = Registry.currentGrid?.getSpacing(); - // TODO - undo this - // this.resolutionToolBar.updateResolutionLabelAndSlider(spacing); - } - - /** - * Gets the coordinates of the project - * @param {*} event - * @returns {Array} Returns the X and Y coordinates - * @memberof ViewManager - */ - getEventPosition(event: any) { - return this.view.getProjectPosition(event.clientX, event.clientY); - } - - /** - * Checks if it has current grid - * @returns {Boolean} - * @memberof ViewManager - */ - __hasCurrentGrid(): boolean { - if (Registry.currentGrid) return true; - else return false; - } - - /** - * Checks if layer is in the current device - * @param {Layer} layer Layer to check if it's on the current device - * @returns {Boolean} - * @memberof ViewManager - */ - __isLayerInCurrentDevice(layer: Layer): boolean { - if (Registry.currentDevice && layer.device === Registry.currentDevice) return true; - else return false; - } - - /** - * Checks if feature is in the current device - * @param {Object} feature Feature to check if it's on the current device - * @returns {Boolean} - * @memberof ViewManager - */ - isFeatureInCurrentDevice(feature: { [k: string]: any }): boolean { - if (Registry.currentDevice && this.__isLayerInCurrentDevice(feature.layer)) return true; - else return false; - } - - /** - * Checks if feature exists - * @param {Feature} feature Feature to check whether in existence - * @returns {Boolean} - * @memberof ViewManager - */ - ensureFeatureExists(feature: Feature): boolean { - for (let i = 0; i < this.renderLayers.length; i++) { - if (this.renderLayers[i].containsFeature(feature)) { - return true; - } - } - return false; - } - - /** - * Loads a device from a JSON format - * @param {JSON} json - * @returns {void} - * @memberof ViewManager - */ - loadDeviceFromJSON(json: InterchangeV1_2): void { - let device; - Registry.viewManager?.clear(); - // Check and see the version number if its 0 or none is present, - // its going the be the legacy format, else it'll be a new format - const version = json.version; - - if (version === null || undefined === version || version === "1" || version == "1.1" || version == "1.2") { - const ret = LoadUtils.loadFromScratch(json); - device = ret[0]; - Registry.currentDevice = device; - this.__currentDevice = device; - - this.renderLayers = ret[1]; - - this.setNameMap(); - // } else if (version == 1.1 || version == "1.1") { - // // this.loadCustomComponents(json); - // device = Device.fromInterchangeV1_1(json); - // Registry.currentDevice = device; - // this.__currentDevice = device; - - // // TODO: Add separate render layers to initializing json, make fromInterchangeV1_1??? - // for (const i in json.layers) { - // const newRenderLayer = RenderLayer.fromInterchangeV1(json.renderLayers[i]); - // this.renderLayers.push(newRenderLayer); - // } - } else { - alert("Version '" + version + "' is not supported by 3DuF !"); - } - // Common Code for rendering stuff - // console.log("Feature Layers", Registry.currentDevice.layers); - this.currentLayer = this.renderLayers[0]; - // Registry.currentTextLayer = Registry.currentDevice!.textLayers[0]; - - this.activeRenderLayerIndex = 0; - - // TODO: Need to replace the need for this function, right now without this, the active layer system gets broken - this.addDevice(Registry.currentDevice!); - - // In case of MINT exported json, generate layouts for rats nests - this.__initializeRatsNest(); - - this.view.initializeView(); - this.updateGrid(); - this.updateDevice(Registry.currentDevice!); - this.refresh(true); - this.currentLayer = this.renderLayers[0]; - // this.layerToolBar.setActiveLayer("0"); - this.updateActiveLayer(); - - - console.log(json.version); - //If older version fix feature locations - if (this.__currentDevice !== null) { - console.log("There"); - console.log("version: ", json.version); - if (json.version == "1" || json.version == "1.1") { - for (const i in this.__currentDevice.components) { - //[center[0] - (center[0] - rect.x), center[1] - (center[1] - rect.y)] - const rect = this.__currentDevice.components[i].getBoundingRectangle(); - const currPos = this.__currentDevice.components[i].getPosition(); - this.__currentDevice.components[i].updateComponentPosition([currPos[0] + (currPos[0] - rect.x), currPos[1] + (currPos[1] - rect.y)]); - } - } - } - } - - /** - * Removes the features of the current device by searching on it's ID - * @param {*} paperElements - * @returns {void} - * @memberof ViewManager - */ - removeFeaturesByPaperElements(paperElements: any): void { - if (paperElements.length > 0) { - for (let i = 0; i < paperElements.length; i++) { - const paperFeature = paperElements[i]; - this.removeFeatureByID(paperFeature.featureID); - } - this.currentSelection = []; - } - } - - /** - * Updates the component parameters of a specific component - * @param {string} componentname - * @param {Array} params - * @returns {void} - * @memberof ViewManager - */ - updateComponentParameters(componentname: string, params: { [k: string]: any }): void { - const component = this.__currentDevice?.getComponentByName(componentname); - for (const key in params) { - component?.updateParameter(key, params[key]); - } - } - - /** - * Returns a Point, coordinate list that is the closes grid coordinate - * @param {Array} point Array with the X and Y coordinates - * @return {void|Array} - * @memberof ViewManager - */ - snapToGrid(point: Point): Point { - if (Registry.currentGrid) - { - const closestpt = Registry.currentGrid.getClosestGridPoint(new paper.Point(point[0], point[1])); - return [closestpt.x, closestpt.y]; - } else { return point; } - } - - /** - * Gets the features of a specific type ? - * @param {string} typeString - * @param {string} setString - * @param {Array} features Array with features - * @returns {Array} Returns array with the features of a specific type - * @memberof ViewManager - */ - getFeaturesOfType(typeString: string, features: Feature[]) { - const output = []; - for (let i = 0; i < features.length; i++) { - const feature = features[i]; - if (feature.getType() === typeString) { - output.push(feature); - } - } - return output; - } - - /** - * Updates all feature parameters - * @param {string} valueString - * @param {*} value - * @param {Array} features Array of features - * @returns {void} - * @memberof ViewManager - */ - adjustAllFeatureParams(valueString: string, value: any, features: Feature[]): void { - for (let i = 0; i < features.length; i++) { - const feature = features[i]; - feature.updateParameter(valueString, value); - } - } - - /** - * Adjust all parameters of the same type - * @param {string} typeString - * @param {string} setString - * @param {string} valueString - * @param {*} value - * @returns {void} - * @memberof ViewManager - */ - adjustParams(typeString: string, valueString: string, value: any): void { - const selectedFeatures = this.view.getSelectedFeatures(); - if (selectedFeatures.length > 0) { - const correctType = this.getFeaturesOfType(typeString, selectedFeatures); - if (correctType.length > 0) { - this.adjustAllFeatureParams(valueString, value, correctType); - } - - // Check if any components are selected - // TODO: modify parameters window to not have chain of updates - // Cycle through all components and connections and change the parameters - for (const i in this.view.selectedComponents) { - this.view.selectedComponents[i].updateParameter(valueString, value); - } - for (const i in this.view.selectedConnections) { - this.view.selectedConnections[i].updateParameter(valueString, value); - } - } else { - this.updateDefault(typeString, valueString, value); - } - } - - /** - * Updates the default feature parameter - * @param {string} typeString - * @param {string} setString - * @param {string} valueString - * @param value - * @returns {void} - * @memberof ViewManager - */ - updateDefault(typeString: string, valueString: string, value: any): void { - // Registry.featureDefaults[setString][typeString][valueString] = value; - const defaults = ComponentAPI.getDefaultsForType(typeString); - defaults[valueString] = value; - } - - /** - * Updates the defaults in the feature - * @param {Feature} feature Feature object - * @returns {void} - * @memberof ViewManager - */ - updateDefaultsFromFeature(feature: Feature): void { - const heritable = feature.getHeritableParams(); - for (const key in heritable) { - this.updateDefault(feature.getType(), key, feature.getValue(key)); - } - } - - /** - * Reverts the feature to default - * @param {string} valueString - * @param {Feature} feature - * @returns {void} - * @memberof ViewManager - */ - revertFieldToDefault(valueString: string, feature: Feature): void { - feature.updateParameter(valueString, ComponentAPI.getDefaultsForType(feature.getType())[valueString]); - } - - /** - * Reverts the feature to params to defaults - * @param {Feature} feature - * @returns {void} - * @memberof ViewManager - */ - revertFeatureToDefaults(feature: Feature): void { - const heritable = feature.getHeritableParams(); - for (const key in heritable) { - this.revertFieldToDefault(key, feature); - } - } - - /** - * Reverts features to defaults - * @param {Array} features Features to revert to default - * @returns {void} - * @memberof ViewManager - */ - revertFeaturesToDefaults(features: Feature[]): void { - for (const feature of features) { - this.revertFeatureToDefaults(feature); - } - } - - /** - * Checks if the point intersects with any other feature - * @param {Array} point Array with the X and Y coordinates - * @return PaperJS rendered Feature - * @memberof ViewManager - */ - hitFeature(point: number[]) { - return this.view.hitFeature((point as unknown) as paper.Point); - } - - /** - * Checks if the point intersects with any other feature - * @param {string} ID of feature object - * @return {Feature} - * @memberof ViewManager - */ - - getFeatureByID(featureID: string) { - const layer = this.getRenderLayerByID(featureID); - return layer.getFeature(featureID); - } - - /** - * Checks if the point intersects with any other feature - * @param {string} ID of feature object - * @return {RenderLayer} - * @memberof ViewManager - */ - getRenderLayerByID(featureID: string) { - for (let i = 0; i < this.renderLayers.length; i++) { - const layer = this.renderLayers[i]; - if (layer.containsFeatureID(featureID)) { - return layer; - } - } - // Should textlayer logic be here or in device? (Currently in device) - // for (let i = 0; i < this.__textLayers.length; i++) { - // let layer = this.__textLayers[i]; - // if (layer.containsFeatureID(featureID)) { - // return layer; - // } - // } - throw new Error("FeatureID " + featureID + " not found in any renderLayer."); - } - - /** - * Checks if the element intersects with any other feature - * @param element - * @return {*|Array} - * @memberof ViewManager - */ - hitFeaturesWithViewElement(element: any): any[] { - return this.view.hitFeaturesWithViewElement(element); - } - - /** - * Activates the given tool - * @param {string} toolString - * @param rightClickToolString - * @returns {void} - * @memberof ViewManager - */ - activateTool(toolString: string, rightClickToolString = "SelectTool"): void { - if (this.tools[toolString] === null) { - throw new Error("Could not find tool with the matching string"); - } - // Cleanup job when activating new tool - this.view.clearSelectedItems(); - - this.mouseAndKeyboardHandler.leftMouseTool = this.tools[toolString]; - this.mouseAndKeyboardHandler.rightMouseTool = this.tools[rightClickToolString]; - this.mouseAndKeyboardHandler.updateViewMouseEvents(); - } - - /** - * Switches to 2D - * @returns {void} - * @memberof ViewManager - */ - switchTo2D(): void { - if (Registry.currentDevice === null){ - throw new Error("No device selected"); - } - if (this.threeD) { - this.threeD = false; - const center = this.renderer.getCameraCenterInMicrometers(); - const zoom = this.renderer.getZoom(); - let newCenterX = center[0]; - if (newCenterX < 0) { - newCenterX = 0; - } else if (newCenterX > Registry.currentDevice.getXSpan()) { - newCenterX = Registry.currentDevice.getXSpan(); - } - let newCenterY = paper.view.center.y - center[1]; - if (newCenterY < 0) { - newCenterY = 0; - } else if (newCenterY > Registry.currentDevice.getYSpan()) { - newCenterY = Registry.currentDevice.getYSpan(); - } - // HTMLUtils.setButtonColor(this.__button2D!, Colors.getDefaultLayerColor((Registry.currentLayer as unknown) as Layer), activeText); - // HTMLUtils.setButtonColor(this.__button3D!, inactiveBackground, inactiveText); - Registry.viewManager!.setCenter((new paper.Point(newCenterX, newCenterY) as unknown) as number[]); - Registry.viewManager!.setZoom(zoom); - // HTMLUtils.addClass(this.__renderBlock!, "hidden-block"); - // HTMLUtils.removeClass(this.__canvasBlock!, "hidden-block"); - // HTMLUtils.removeClass(this.__renderBlock!, "shown-block"); - // HTMLUtils.addClass(this.__canvasBlock!, "shown-block"); - } - } - - /** - * Switches to 3D - * @returns {void} - * @memberof ViewManager - */ - switchTo3D(): void { - if (!this.threeD) { - this.threeD = true; - // setButtonColor(this.__button3D!, Colors.getDefaultLayerColor(Registry.currentLayer as any), activeText); - // setButtonColor(this.__button2D!!, inactiveBackground, inactiveText); - this.renderer.loadJSON((Registry.currentDevice as any).toJSON()); - const cameraCenter = this.view.getViewCenterInMillimeters(); - const height = (Registry.currentDevice as any).params.getValue("height") / 1000; - const pixels = this.view.getDeviceHeightInPixels(); - this.renderer.setupCamera(cameraCenter[0], cameraCenter[1], height, pixels, paper.view.zoom); - this.renderer.showMockup(); - HTMLUtils.removeClass(this.__renderBlock!, "hidden-block"); - HTMLUtils.addClass(this.__canvasBlock!, "hidden-block"); - HTMLUtils.addClass(this.__renderBlock!, "shown-block"); - HTMLUtils.removeClass(this.__canvasBlock!, "shown-block"); - } - } - - /** - * Loads a device from a JSON format when the user drags and drops it on the grid - * @param selector - * @returns {void} - * @memberof ViewManager - */ - setupDragAndDropLoad(selector: string): void { - const dnd = HTMLUtils.DnDFileController(selector, function(files) { - const f = files[0]; - - const reader = new FileReader(); - reader.onloadend = function(e) { - let result = this.result as string; - // try { - let jsonresult = JSON.parse(result); - Registry.viewManager?.loadDeviceFromJSON((jsonresult as unknown) as InterchangeV1_2); - // } catch (error) { - // console.error(error.message); - // alert("Unable to parse the design file, please ensure that the file is not corrupted:\n" + error.message); - // } - }; - try { - reader.readAsText(f); - } catch (err) { - console.log("unable to load JSON: " + f); - } - }); - } - - /** - * Closes the params window - * @returns {void} - * @memberof ViewManager - */ - killParamsWindow(): void { - const paramsWindow = document.getElementById("parameter_menu"); - if (paramsWindow) paramsWindow.parentElement?.removeChild(paramsWindow); - } - - /** - * This method saves the current device to the design history - * @memberof ViewManager - * @returns {void} - */ - saveDeviceState(): void { - console.log("Saving to stack"); - - // TODO - Future versions of the software should be using the saving - // the device as a set of atomic operations and not as the json data - // unless we are using it as a refernce. - const save = JSON.stringify(Registry.currentDevice?.toInterchangeV1([])); - - this.undoStack.pushDesign(save); - } - - /** - * Undoes the recent update - * @returns {void} - * @memberof ViewManager - */ - undo(): void { - const previousdesign = this.undoStack.popDesign(); - console.log(previousdesign); - if (previousdesign) { - const result = JSON.parse(previousdesign); - this.loadDeviceFromJSON(result); - } - } - - /** - * Resets the tool to the default tool - * @returns {void} - * @memberof ViewManager - */ - resetToDefaultTool(): void { - this.cleanupActiveTools(); - this.activateTool("MouseSelectTool"); - // this.activateTool("RenderMouseTool"); - // this.componentToolBar.setActiveButton("SelectButton"); - } - - /** - * Runs cleanup method on the activated tools - * @returns {void} - * @memberof ViewManager - */ - cleanupActiveTools(): void { - if (this.mouseAndKeyboardHandler.leftMouseTool) { - this.mouseAndKeyboardHandler.leftMouseTool.cleanup(); - } - if (this.mouseAndKeyboardHandler.rightMouseTool) { - this.mouseAndKeyboardHandler.rightMouseTool.cleanup(); - } - } - - /** - * Updates the renders for all the connection in the blah - * @returns {void} - * @memberof ViewManager - */ - updatesConnectionRender(connection: Connection): void { - // First Redraw all the segements without valves or insertions - connection.regenerateSegments(); - - // Get all the valves for a connection - const valves = Registry.currentDevice?.getValvesForConnection(connection); - - // Cycle through each of the valves - if (valves === undefined || valves === null) { - throw new Error("Valves are undefined or null when updating connection: " + connection.id); - } - for (const j in valves) { - const valve = valves[j]; - const is3D = Registry.currentDevice?.getValveType(valve); - if (is3D) { - const boundingbox = valve.getBoundingRectangle(); - connection.insertFeatureGap(boundingbox); - } - } - } - - /** - * Shows in the UI a message - * @param {string} message Messsage to display - * @returns {void} - * @memberof ViewManager - */ - showUIMessage(message: string): void { - this.messageBox.MaterialSnackbar.showSnackbar({ - message: message - }); - } - - /** - * Sets up all the tools to be used by the user - * @returns {void} - * @memberof ViewManager - */ - setupTools(): void { - this.tools.MouseSelectTool = new MouseSelectTool(this, this.view); - // this.tools.RenderMouseTool = new RenderMouseTool(this, this.view); - this.tools.InsertTextTool = new InsertTextTool(this); - this.tools.Connection = new ConnectionTool(this, "Connection", "Basic"); - // All the new tools - this.tools.MoveTool = new MoveTool(this); - this.tools.GenerateArrayTool = new GenerateArrayTool(this); - - } - - /** - * Adds a custom component tool - * @param {string} identifier - * @returns {void} - * @memberof ViewManager - */ - addCustomComponentTool(identifier: string): void { - const customcomponent = this.customComponentManager?.getCustomComponent(identifier); - this.tools[identifier] = new CustomComponentPositionTool(this, customcomponent, "Custom"); - } - - /** - * Initialize the default placement for components - * @returns {void} - * @memberof ViewManager - */ - __initializeRatsNest(): void { - // Step 1 generate features for all the components with some basic layout - const components = this.currentDevice?.components; - const xpos = 10000; - const ypos = 10000; - for (const i in components) { - const component = components[parseInt(i)]; - const currentposition = component.getPosition(); - // TODO: Refine this logic, it sucks - if (currentposition[0] === 0 && currentposition[1] === 0) { - if (!component.placed) { - this.__generateDefaultPlacementForComponent(component, xpos * (parseInt(i) + 1), ypos * (Math.floor(parseInt(i) / 5) + 1)); - } - } else { - if (!component.placed) { - this.__generateDefaultPlacementForComponent(component, currentposition[0], currentposition[1]); - } - } - } - - // TODO: Step 2 generate rats nest renders for all the components - - this.view.updateRatsNest(); - this.view.updateComponentPortsRender(); - } - - /** - * Generates the default placement for components - * @param {Component} component - * @param {number} xpos Default X coordinate - * @param {number} ypos Default Y coordinate - * @returns {void} - * @memberof ViewManager - */ - __generateDefaultPlacementForComponent(component: Component, xpos: number, ypos: number): void { - const params_to_copy = component.params.toJSON(); - - params_to_copy.position = [xpos, ypos]; - - // Get default params and overwrite them with json params, this can account for inconsistencies - const renderdefkeys = ComponentAPI.getRenderTypeKeysForMINT(component.mint); - for (let i = 0; i < renderdefkeys?.length!; i++) { - const key = renderdefkeys![i]; - const newFeature = Device.makeFeature(key, params_to_copy); - component.addFeatureID(newFeature.ID); - this.currentLayer.addFeature(newFeature); - } - - // Set the component position - component.updateComponentPosition([xpos, ypos]); - } - - /** - * Generates a JSON format file to export it - * @returns {void} - * @memberof ViewManager - */ - generateExportJSON(errorList:Array = []): InterchangeV1_2 { - const json = ExportUtils.toInterchangeV1_2(this, errorList); - // const json = this.currentDevice.toInterchangeV1_1(); - // json.customComponents = this.customComponentManager.toJSON(); - return json; - } - - /** - * This method attempts to load any custom components that are stored in the custom components property - * @param json - */ - loadCustomComponents(json: { [key: string]: any }): void { - if (Object.prototype.hasOwnProperty.call(json, "customComponents")) { - this.customComponentManager?.loadFromJSON(json.customComponents); - } - } - - /** - * Activates DAFD plugin - * @param {*} params - * @returns {void} - * @memberof ViewManager - */ - activateDAFDPlugin(params: any = null): void { - this.loadDeviceFromJSON(JSON.parse(Examples.dafdtemplate)); - - if (params === null) { - params = { - orificeSize: 750, - orificeLength: 200, - oilInputWidth: 800, - waterInputWidth: 900, - outputWidth: 900, - outputLength: 500, - height: 100 - }; - } - - DAFDPlugin.fixLayout(params); - } - - /** - * This is the method we need to call to fix the valvemaps - * @memberof ViewManager - */ - createValveMapFromSelection():void { - // TODO: Run through the current selection and generate the valve map for every - // vavle that is in the Selection - const selection = this.tools.MouseSelectTool.currentSelection; - const valves = []; - let connection = null; - // TODO: run though the items - for (const render_element of selection) { - // Check if render_element is associated with a VALVE/VALVE3D - const component = this.currentDevice!.getComponentForFeatureID(render_element.featureID); - if (component !== null) { - console.log("Component Type:", component.mint); - const type = (component as any).getType(); - if (type === "VALVE3D" || type === "VALVE") { - valves.push(component); - } - } - - connection = this.currentDevice!.getConnectionForFeatureID(render_element.featureID); - } - - // Add to the valvemap - for (const valve of valves) { - let valve_type = ValveType.NORMALLY_OPEN; - if (valve.mint === "VALVE3D") { - valve_type = ValveType.NORMALLY_CLOSED; - } - console.log("Adding Valve: ", valve); - this.currentDevice!.insertValve(valve, connection!, valve_type); - } - } - - /** - * Activates the corresponding placement tool for the given type of component and returns the active tool - * @param {*} minttype - * @returns - */ - activateComponentPlacementTool(minttype: string, currentParameters: any): PositionTool | ValveInsertionTool | ConnectionTool { - const threeduftype = ComponentAPI.getTypeForMINT(minttype); - if (threeduftype === null) { - throw new Error("Found null when looking for MINT Type"); - } - // Cleanup job when activating new tool - this.view.clearSelectedItems(); - - let activeTool = null; - const renderer = ComponentAPI.getRendererForMINT(minttype); - if (renderer.placementTool === "componentPositionTool") { - activeTool = new ComponentPositionTool(this, threeduftype , "Basic", currentParameters); - } else if (renderer.placementTool === "customComponentPositionTool") { - // activeTool = new CustomComponentPositionTool(ComponentAPI.getTypeForMINT(minttype), "Basic"); - } else if (renderer.placementTool === "positionTool") { - activeTool = new PositionTool(this, threeduftype, currentParameters); - } else if (renderer.placementTool === "multilayerPositionTool") { - activeTool = new MultilayerPositionTool(this, threeduftype, "Basic", currentParameters); - } else if (renderer.placementTool === "valveInsertionTool") { - activeTool = new ValveInsertionTool(this, minttype, "Basic", currentParameters); - } else if (renderer.placementTool === "CellPositionTool") { - activeTool = new CellPositionTool(this, threeduftype, "Basic", currentParameters); - } else if (renderer.placementTool === "multilevelPositionTool") { - // TODO: Add pop up window when using the multilevel position tool to get layer indices - activeTool = new MultilevelPositionTool(this, threeduftype, "Basic", currentParameters); - throw new Error("multilevel position tool ui/input elements not set up"); - }else if(renderer.placementTool === "connectionTool"){ - activeTool = new ConnectionTool(this, threeduftype, "Basic"); - } - - if (activeTool === null) { - throw new Error(`Could not initialize the tool ${minttype}`); - } - - this.mouseAndKeyboardHandler.leftMouseTool = activeTool; - this.mouseAndKeyboardHandler.rightMouseTool = activeTool; - this.mouseAndKeyboardHandler.updateViewMouseEvents(); - - return activeTool; - } - - /** - * Deactivates the current placement tool - * - * @memberof ViewManager - */ - deactivateComponentPlacementTool(): void { - console.log("Deactivating Component Placement Tool"); - this.mouseAndKeyboardHandler.leftMouseTool.deactivate(); - this.mouseAndKeyboardHandler.rightMouseTool.deactivate(); - this.resetToDefaultTool(); - } - - /** - * Returns the spacing for the current grid on the device - * - * @returns - * @memberof ViewManager - */ - getGridSize(): number { - if (this.__grid === null) { - return 0; - } - return this.__grid.spacing; - } - - /** - * Updated the grid size for the current view - * - * @param {number} value - * @memberof ViewManager - */ - updateGridSpacing(value: number):void { - this.__grid.updateGridSpacing(value); - this.updateGrid(); - } - - /** - * Starts the download sequence for the current device - * - * @memberof ViewManager - */ - downloadJSON(): void { - if(this.currentDevice === null){ - throw new Error("No device loaded"); - } - const errorList: Array = []; - const json = new Blob([JSON.stringify(this.generateExportJSON(errorList))], { - type: "application/json" - }); - saveAs(json, this.currentDevice.name + ".json"); - - if (errorList.length > 0) { - // Concatenate all the errors into a single string with newlines and save it as a file - let errorString = ""; - for (const error of errorList) { - errorString += error.toText() + "\n\n"; - } - const errorBlob = new Blob([errorString], { - type: "text/plain" - }); - saveAs(errorBlob, this.currentDevice.name + "_errors.txt"); - } - } - - createNewDevice(name: string): void { - let device = new Device({"x-span": 135000, "y-span": 85000}, name); - console.log("Created new device: ", device.getXSpan(), device.getYSpan()); - this.clear(); - this.__currentDevice = device; - // TODO - Clean up lifecyle for active rendered layers - this.activeRenderLayerIndex = 0; - this.createNewLayerBlock(); - // TODO - Generate render layers - generateRenderLayers(this.__currentDevice); - this.setNameMap(); - - Registry.currentDevice = device; - - this.activeRenderLayerIndex = 0; - - this.addDevice(device); - - // In case of MINT exported json, generate layouts for rats nests - this.__initializeRatsNest(); - - this.view.initializeView(); - this.updateGrid(); - this.updateDevice(Registry.currentDevice!); - this.refresh(true); - this.currentLayer = this.renderLayers[0]; - this.updateActiveLayer(); - - } - - /** - * Ridiculously convoluted method to return the render layers corresponding to the current level - * To be used in the case of creating multi-level components - * @returns {[any, any, any]} - * @memberof ViewManager - */ - getCurrentLevelRenderLayers(): [RenderLayer | null , RenderLayer | null , RenderLayer | null] { - // Get the current level - const currentLevel = this.activeRenderLayerIndex % 3; - let currentFlowLayerIndex = currentLevel * 3 + 0; - let currentControlLayerIndex = currentLevel * 3 + 1; - let currentIntegrationLayerIndex = currentLevel * 3 + 2; - return [this.renderLayers[currentFlowLayerIndex], this.renderLayers[currentControlLayerIndex], this.renderLayers[currentIntegrationLayerIndex]]; - } - - -} diff --git a/src/assets/lib/nouislider/nouislider.d.ts b/src/assets/lib/nouislider/nouislider.d.ts deleted file mode 100644 index ea575eee..00000000 --- a/src/assets/lib/nouislider/nouislider.d.ts +++ /dev/null @@ -1,198 +0,0 @@ -interface CssClasses { - target: string; - base: string; - origin: string; - handle: string; - handleLower: string; - handleUpper: string; - touchArea: string; - horizontal: string; - vertical: string; - background: string; - connect: string; - connects: string; - ltr: string; - rtl: string; - textDirectionLtr: string; - textDirectionRtl: string; - draggable: string; - drag: string; - tap: string; - active: string; - tooltip: string; - pips: string; - pipsHorizontal: string; - pipsVertical: string; - marker: string; - markerHorizontal: string; - markerVertical: string; - markerNormal: string; - markerLarge: string; - markerSub: string; - value: string; - valueHorizontal: string; - valueVertical: string; - valueNormal: string; - valueLarge: string; - valueSub: string; -} -export interface PartialFormatter { - to: (value: number) => string | number; - from?: (value: string) => number | false; -} -export interface Formatter extends PartialFormatter { - from: (value: string) => number | false; -} -export declare enum PipsMode { - Range = "range", - Steps = "steps", - Positions = "positions", - Count = "count", - Values = "values" -} -export declare enum PipsType { - None = -1, - NoValue = 0, - LargeValue = 1, - SmallValue = 2 -} -declare type WrappedSubRange = [number] | [number, number]; -declare type SubRange = number | WrappedSubRange; -interface Range { - min: SubRange; - max: SubRange; - [key: string]: SubRange; -} -interface BasePips { - mode: PipsMode; - density?: number; - filter?: PipsFilter; - format?: PartialFormatter; -} -interface PositionsPips extends BasePips { - mode: PipsMode.Positions; - values: number[]; - stepped?: boolean; -} -interface ValuesPips extends BasePips { - mode: PipsMode.Values; - values: number[]; - stepped?: boolean; -} -interface CountPips extends BasePips { - mode: PipsMode.Count; - values: number; - stepped?: boolean; -} -interface StepsPips extends BasePips { - mode: PipsMode.Steps; -} -interface RangePips extends BasePips { - mode: PipsMode.Range; -} -declare type Pips = PositionsPips | ValuesPips | CountPips | StepsPips | RangePips; -declare type StartValues = string | number | (string | number)[]; -declare type HandleAttributes = { - [key: string]: string; -}; -interface UpdatableOptions { - range?: Range; - start?: StartValues; - margin?: number; - limit?: number; - padding?: number | number[]; - snap?: boolean; - step?: number; - pips?: Pips; - format?: Formatter; - tooltips?: boolean | PartialFormatter | (boolean | PartialFormatter)[]; - animate?: boolean; -} -export interface Options extends UpdatableOptions { - range: Range; - connect?: "lower" | "upper" | boolean | boolean[]; - orientation?: "vertical" | "horizontal"; - direction?: "ltr" | "rtl"; - behaviour?: string; - keyboardSupport?: boolean; - keyboardPageMultiplier?: number; - keyboardMultiplier?: number; - keyboardDefaultStep?: number; - documentElement?: HTMLElement; - cssPrefix?: string; - cssClasses?: CssClasses; - ariaFormat?: PartialFormatter; - animationDuration?: number; - handleAttributes?: HandleAttributes[]; -} -export interface API { - destroy: () => void; - steps: () => NextStepsForHandle[]; - on: (eventName: string, callback: EventCallback) => void; - off: (eventName: string) => void; - get: (unencoded?: boolean) => GetResult; - set: (input: number | string | (number | string)[], fireSetEvent?: boolean, exactInput?: boolean) => void; - setHandle: (handleNumber: number, value: number | string, fireSetEvent?: boolean, exactInput?: boolean) => void; - reset: (fireSetEvent?: boolean) => void; - options: Options; - updateOptions: (optionsToUpdate: UpdatableOptions, fireSetEvent: boolean) => void; - target: HTMLElement; - removePips: () => void; - removeTooltips: () => void; - getTooltips: () => { - [handleNumber: number]: HTMLElement | false; - }; - getOrigins: () => { - [handleNumber: number]: HTMLElement; - }; - pips: (grid: Pips) => HTMLElement; -} -interface TargetElement extends HTMLElement { - noUiSlider?: API; -} -interface NearByStep { - startValue: number; - step: number | false; - highestStep: number; -} -interface NearBySteps { - stepBefore: NearByStep; - thisStep: NearByStep; - stepAfter: NearByStep; -} -declare type GetResult = number | string | (string | number)[]; -declare type NextStepsForHandle = [number | false | null, number | false | null]; -declare type PipsFilter = (value: number, type: PipsType) => PipsType; -declare type EventCallback = (this: API, values: (number | string)[], handleNumber: number, unencoded: number[], tap: boolean, locations: number[], slider: API) => void; -declare class Spectrum { - xPct: number[]; - xVal: number[]; - xSteps: (number | false)[]; - xNumSteps: (number | false)[]; - protected xHighestCompleteStep: number[]; - protected snap: boolean; - constructor(entry: Range, snap: boolean, singleStep: number); - getDistance(value: number): number[]; - getAbsoluteDistance(value: number, distances: number[] | null, direction: boolean): number; - toStepping(value: number): number; - fromStepping(value: number): number; - getStep(value: number): number; - getDefaultStep(value: number, isDown: boolean, size: number): number; - getNearbySteps(value: number): NearBySteps; - countStepDecimals(): number; - hasNoSize(): boolean; - convert(value: number): number; - private handleEntryPoint; - private handleStepPoint; -} -declare const cssClasses: CssClasses; -declare function initialize(target: TargetElement, originalOptions: Options): API; -export { TargetElement as target }; -export { initialize as create }; -export { cssClasses }; -declare const _default: { - __spectrum: typeof Spectrum; - cssClasses: CssClasses; - create: typeof initialize; -}; -export default _default; diff --git a/src/assets/lib/nouislider/nouislider.js b/src/assets/lib/nouislider/nouislider.js deleted file mode 100644 index 01fc0bc1..00000000 --- a/src/assets/lib/nouislider/nouislider.js +++ /dev/null @@ -1,2254 +0,0 @@ -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : - typeof define === 'function' && define.amd ? define(['exports'], factory) : - (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.noUiSlider = {})); -})(this, (function (exports) { 'use strict'; - - exports.PipsMode = void 0; - (function (PipsMode) { - PipsMode["Range"] = "range"; - PipsMode["Steps"] = "steps"; - PipsMode["Positions"] = "positions"; - PipsMode["Count"] = "count"; - PipsMode["Values"] = "values"; - })(exports.PipsMode || (exports.PipsMode = {})); - exports.PipsType = void 0; - (function (PipsType) { - PipsType[PipsType["None"] = -1] = "None"; - PipsType[PipsType["NoValue"] = 0] = "NoValue"; - PipsType[PipsType["LargeValue"] = 1] = "LargeValue"; - PipsType[PipsType["SmallValue"] = 2] = "SmallValue"; - })(exports.PipsType || (exports.PipsType = {})); - //region Helper Methods - function isValidFormatter(entry) { - return isValidPartialFormatter(entry) && typeof entry.from === "function"; - } - function isValidPartialFormatter(entry) { - // partial formatters only need a to function and not a from function - return typeof entry === "object" && typeof entry.to === "function"; - } - function removeElement(el) { - el.parentElement.removeChild(el); - } - function isSet(value) { - return value !== null && value !== undefined; - } - // Bindable version - function preventDefault(e) { - e.preventDefault(); - } - // Removes duplicates from an array. - function unique(array) { - return array.filter(function (a) { - return !this[a] ? (this[a] = true) : false; - }, {}); - } - // Round a value to the closest 'to'. - function closest(value, to) { - return Math.round(value / to) * to; - } - // Current position of an element relative to the document. - function offset(elem, orientation) { - var rect = elem.getBoundingClientRect(); - var doc = elem.ownerDocument; - var docElem = doc.documentElement; - var pageOffset = getPageOffset(doc); - // getBoundingClientRect contains left scroll in Chrome on Android. - // I haven't found a feature detection that proves this. Worst case - // scenario on mis-match: the 'tap' feature on horizontal sliders breaks. - if (/webkit.*Chrome.*Mobile/i.test(navigator.userAgent)) { - pageOffset.x = 0; - } - return orientation ? rect.top + pageOffset.y - docElem.clientTop : rect.left + pageOffset.x - docElem.clientLeft; - } - // Checks whether a value is numerical. - function isNumeric(a) { - return typeof a === "number" && !isNaN(a) && isFinite(a); - } - // Sets a class and removes it after [duration] ms. - function addClassFor(element, className, duration) { - if (duration > 0) { - addClass(element, className); - setTimeout(function () { - removeClass(element, className); - }, duration); - } - } - // Limits a value to 0 - 100 - function limit(a) { - return Math.max(Math.min(a, 100), 0); - } - // Wraps a variable as an array, if it isn't one yet. - // Note that an input array is returned by reference! - function asArray(a) { - return Array.isArray(a) ? a : [a]; - } - // Counts decimals - function countDecimals(numStr) { - numStr = String(numStr); - var pieces = numStr.split("."); - return pieces.length > 1 ? pieces[1].length : 0; - } - // http://youmightnotneedjquery.com/#add_class - function addClass(el, className) { - if (el.classList && !/\s/.test(className)) { - el.classList.add(className); - } - else { - el.className += " " + className; - } - } - // http://youmightnotneedjquery.com/#remove_class - function removeClass(el, className) { - if (el.classList && !/\s/.test(className)) { - el.classList.remove(className); - } - else { - el.className = el.className.replace(new RegExp("(^|\\b)" + className.split(" ").join("|") + "(\\b|$)", "gi"), " "); - } - } - // https://plainjs.com/javascript/attributes/adding-removing-and-testing-for-classes-9/ - function hasClass(el, className) { - return el.classList ? el.classList.contains(className) : new RegExp("\\b" + className + "\\b").test(el.className); - } - // https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollY#Notes - function getPageOffset(doc) { - var supportPageOffset = window.pageXOffset !== undefined; - var isCSS1Compat = (doc.compatMode || "") === "CSS1Compat"; - var x = supportPageOffset - ? window.pageXOffset - : isCSS1Compat - ? doc.documentElement.scrollLeft - : doc.body.scrollLeft; - var y = supportPageOffset - ? window.pageYOffset - : isCSS1Compat - ? doc.documentElement.scrollTop - : doc.body.scrollTop; - return { - x: x, - y: y, - }; - } - // we provide a function to compute constants instead - // of accessing window.* as soon as the module needs it - // so that we do not compute anything if not needed - function getActions() { - // Determine the events to bind. IE11 implements pointerEvents without - // a prefix, which breaks compatibility with the IE10 implementation. - return window.navigator.pointerEnabled - ? { - start: "pointerdown", - move: "pointermove", - end: "pointerup", - } - : window.navigator.msPointerEnabled - ? { - start: "MSPointerDown", - move: "MSPointerMove", - end: "MSPointerUp", - } - : { - start: "mousedown touchstart", - move: "mousemove touchmove", - end: "mouseup touchend", - }; - } - // https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md - // Issue #785 - function getSupportsPassive() { - var supportsPassive = false; - /* eslint-disable */ - try { - var opts = Object.defineProperty({}, "passive", { - get: function () { - supportsPassive = true; - }, - }); - // @ts-ignore - window.addEventListener("test", null, opts); - } - catch (e) { } - /* eslint-enable */ - return supportsPassive; - } - function getSupportsTouchActionNone() { - return window.CSS && CSS.supports && CSS.supports("touch-action", "none"); - } - //endregion - //region Range Calculation - // Determine the size of a sub-range in relation to a full range. - function subRangeRatio(pa, pb) { - return 100 / (pb - pa); - } - // (percentage) How many percent is this value of this range? - function fromPercentage(range, value, startRange) { - return (value * 100) / (range[startRange + 1] - range[startRange]); - } - // (percentage) Where is this value on this range? - function toPercentage(range, value) { - return fromPercentage(range, range[0] < 0 ? value + Math.abs(range[0]) : value - range[0], 0); - } - // (value) How much is this percentage on this range? - function isPercentage(range, value) { - return (value * (range[1] - range[0])) / 100 + range[0]; - } - function getJ(value, arr) { - var j = 1; - while (value >= arr[j]) { - j += 1; - } - return j; - } - // (percentage) Input a value, find where, on a scale of 0-100, it applies. - function toStepping(xVal, xPct, value) { - if (value >= xVal.slice(-1)[0]) { - return 100; - } - var j = getJ(value, xVal); - var va = xVal[j - 1]; - var vb = xVal[j]; - var pa = xPct[j - 1]; - var pb = xPct[j]; - return pa + toPercentage([va, vb], value) / subRangeRatio(pa, pb); - } - // (value) Input a percentage, find where it is on the specified range. - function fromStepping(xVal, xPct, value) { - // There is no range group that fits 100 - if (value >= 100) { - return xVal.slice(-1)[0]; - } - var j = getJ(value, xPct); - var va = xVal[j - 1]; - var vb = xVal[j]; - var pa = xPct[j - 1]; - var pb = xPct[j]; - return isPercentage([va, vb], (value - pa) * subRangeRatio(pa, pb)); - } - // (percentage) Get the step that applies at a certain value. - function getStep(xPct, xSteps, snap, value) { - if (value === 100) { - return value; - } - var j = getJ(value, xPct); - var a = xPct[j - 1]; - var b = xPct[j]; - // If 'snap' is set, steps are used as fixed points on the slider. - if (snap) { - // Find the closest position, a or b. - if (value - a > (b - a) / 2) { - return b; - } - return a; - } - if (!xSteps[j - 1]) { - return value; - } - return xPct[j - 1] + closest(value - xPct[j - 1], xSteps[j - 1]); - } - //endregion - //region Spectrum - var Spectrum = /** @class */ (function () { - function Spectrum(entry, snap, singleStep) { - this.xPct = []; - this.xVal = []; - this.xSteps = []; - this.xNumSteps = []; - this.xHighestCompleteStep = []; - this.xSteps = [singleStep || false]; - this.xNumSteps = [false]; - this.snap = snap; - var index; - var ordered = []; - // Map the object keys to an array. - Object.keys(entry).forEach(function (index) { - ordered.push([asArray(entry[index]), index]); - }); - // Sort all entries by value (numeric sort). - ordered.sort(function (a, b) { - return a[0][0] - b[0][0]; - }); - // Convert all entries to subranges. - for (index = 0; index < ordered.length; index++) { - this.handleEntryPoint(ordered[index][1], ordered[index][0]); - } - // Store the actual step values. - // xSteps is sorted in the same order as xPct and xVal. - this.xNumSteps = this.xSteps.slice(0); - // Convert all numeric steps to the percentage of the subrange they represent. - for (index = 0; index < this.xNumSteps.length; index++) { - this.handleStepPoint(index, this.xNumSteps[index]); - } - } - Spectrum.prototype.getDistance = function (value) { - var distances = []; - for (var index = 0; index < this.xNumSteps.length - 1; index++) { - distances[index] = fromPercentage(this.xVal, value, index); - } - return distances; - }; - // Calculate the percentual distance over the whole scale of ranges. - // direction: 0 = backwards / 1 = forwards - Spectrum.prototype.getAbsoluteDistance = function (value, distances, direction) { - var xPct_index = 0; - // Calculate range where to start calculation - if (value < this.xPct[this.xPct.length - 1]) { - while (value > this.xPct[xPct_index + 1]) { - xPct_index++; - } - } - else if (value === this.xPct[this.xPct.length - 1]) { - xPct_index = this.xPct.length - 2; - } - // If looking backwards and the value is exactly at a range separator then look one range further - if (!direction && value === this.xPct[xPct_index + 1]) { - xPct_index++; - } - if (distances === null) { - distances = []; - } - var start_factor; - var rest_factor = 1; - var rest_rel_distance = distances[xPct_index]; - var range_pct = 0; - var rel_range_distance = 0; - var abs_distance_counter = 0; - var range_counter = 0; - // Calculate what part of the start range the value is - if (direction) { - start_factor = (value - this.xPct[xPct_index]) / (this.xPct[xPct_index + 1] - this.xPct[xPct_index]); - } - else { - start_factor = (this.xPct[xPct_index + 1] - value) / (this.xPct[xPct_index + 1] - this.xPct[xPct_index]); - } - // Do until the complete distance across ranges is calculated - while (rest_rel_distance > 0) { - // Calculate the percentage of total range - range_pct = this.xPct[xPct_index + 1 + range_counter] - this.xPct[xPct_index + range_counter]; - // Detect if the margin, padding or limit is larger then the current range and calculate - if (distances[xPct_index + range_counter] * rest_factor + 100 - start_factor * 100 > 100) { - // If larger then take the percentual distance of the whole range - rel_range_distance = range_pct * start_factor; - // Rest factor of relative percentual distance still to be calculated - rest_factor = (rest_rel_distance - 100 * start_factor) / distances[xPct_index + range_counter]; - // Set start factor to 1 as for next range it does not apply. - start_factor = 1; - } - else { - // If smaller or equal then take the percentual distance of the calculate percentual part of that range - rel_range_distance = ((distances[xPct_index + range_counter] * range_pct) / 100) * rest_factor; - // No rest left as the rest fits in current range - rest_factor = 0; - } - if (direction) { - abs_distance_counter = abs_distance_counter - rel_range_distance; - // Limit range to first range when distance becomes outside of minimum range - if (this.xPct.length + range_counter >= 1) { - range_counter--; - } - } - else { - abs_distance_counter = abs_distance_counter + rel_range_distance; - // Limit range to last range when distance becomes outside of maximum range - if (this.xPct.length - range_counter >= 1) { - range_counter++; - } - } - // Rest of relative percentual distance still to be calculated - rest_rel_distance = distances[xPct_index + range_counter] * rest_factor; - } - return value + abs_distance_counter; - }; - Spectrum.prototype.toStepping = function (value) { - value = toStepping(this.xVal, this.xPct, value); - return value; - }; - Spectrum.prototype.fromStepping = function (value) { - return fromStepping(this.xVal, this.xPct, value); - }; - Spectrum.prototype.getStep = function (value) { - value = getStep(this.xPct, this.xSteps, this.snap, value); - return value; - }; - Spectrum.prototype.getDefaultStep = function (value, isDown, size) { - var j = getJ(value, this.xPct); - // When at the top or stepping down, look at the previous sub-range - if (value === 100 || (isDown && value === this.xPct[j - 1])) { - j = Math.max(j - 1, 1); - } - return (this.xVal[j] - this.xVal[j - 1]) / size; - }; - Spectrum.prototype.getNearbySteps = function (value) { - var j = getJ(value, this.xPct); - return { - stepBefore: { - startValue: this.xVal[j - 2], - step: this.xNumSteps[j - 2], - highestStep: this.xHighestCompleteStep[j - 2], - }, - thisStep: { - startValue: this.xVal[j - 1], - step: this.xNumSteps[j - 1], - highestStep: this.xHighestCompleteStep[j - 1], - }, - stepAfter: { - startValue: this.xVal[j], - step: this.xNumSteps[j], - highestStep: this.xHighestCompleteStep[j], - }, - }; - }; - Spectrum.prototype.countStepDecimals = function () { - var stepDecimals = this.xNumSteps.map(countDecimals); - return Math.max.apply(null, stepDecimals); - }; - Spectrum.prototype.hasNoSize = function () { - return this.xVal[0] === this.xVal[this.xVal.length - 1]; - }; - // Outside testing - Spectrum.prototype.convert = function (value) { - return this.getStep(this.toStepping(value)); - }; - Spectrum.prototype.handleEntryPoint = function (index, value) { - var percentage; - // Covert min/max syntax to 0 and 100. - if (index === "min") { - percentage = 0; - } - else if (index === "max") { - percentage = 100; - } - else { - percentage = parseFloat(index); - } - // Check for correct input. - if (!isNumeric(percentage) || !isNumeric(value[0])) { - throw new Error("noUiSlider: 'range' value isn't numeric."); - } - // Store values. - this.xPct.push(percentage); - this.xVal.push(value[0]); - var value1 = Number(value[1]); - // NaN will evaluate to false too, but to keep - // logging clear, set step explicitly. Make sure - // not to override the 'step' setting with false. - if (!percentage) { - if (!isNaN(value1)) { - this.xSteps[0] = value1; - } - } - else { - this.xSteps.push(isNaN(value1) ? false : value1); - } - this.xHighestCompleteStep.push(0); - }; - Spectrum.prototype.handleStepPoint = function (i, n) { - // Ignore 'false' stepping. - if (!n) { - return; - } - // Step over zero-length ranges (#948); - if (this.xVal[i] === this.xVal[i + 1]) { - this.xSteps[i] = this.xHighestCompleteStep[i] = this.xVal[i]; - return; - } - // Factor to range ratio - this.xSteps[i] = - fromPercentage([this.xVal[i], this.xVal[i + 1]], n, 0) / subRangeRatio(this.xPct[i], this.xPct[i + 1]); - var totalSteps = (this.xVal[i + 1] - this.xVal[i]) / this.xNumSteps[i]; - var highestStep = Math.ceil(Number(totalSteps.toFixed(3)) - 1); - var step = this.xVal[i] + this.xNumSteps[i] * highestStep; - this.xHighestCompleteStep[i] = step; - }; - return Spectrum; - }()); - //endregion - //region Options - /* Every input option is tested and parsed. This will prevent - endless validation in internal methods. These tests are - structured with an item for every option available. An - option can be marked as required by setting the 'r' flag. - The testing function is provided with three arguments: - - The provided value for the option; - - A reference to the options object; - - The name for the option; - - The testing function returns false when an error is detected, - or true when everything is OK. It can also modify the option - object, to make sure all values can be correctly looped elsewhere. */ - //region Defaults - var defaultFormatter = { - to: function (value) { - return value === undefined ? "" : value.toFixed(2); - }, - from: Number, - }; - var cssClasses = { - target: "target", - base: "base", - origin: "origin", - handle: "handle", - handleLower: "handle-lower", - handleUpper: "handle-upper", - touchArea: "touch-area", - horizontal: "horizontal", - vertical: "vertical", - background: "background", - connect: "connect", - connects: "connects", - ltr: "ltr", - rtl: "rtl", - textDirectionLtr: "txt-dir-ltr", - textDirectionRtl: "txt-dir-rtl", - draggable: "draggable", - drag: "state-drag", - tap: "state-tap", - active: "active", - tooltip: "tooltip", - pips: "pips", - pipsHorizontal: "pips-horizontal", - pipsVertical: "pips-vertical", - marker: "marker", - markerHorizontal: "marker-horizontal", - markerVertical: "marker-vertical", - markerNormal: "marker-normal", - markerLarge: "marker-large", - markerSub: "marker-sub", - value: "value", - valueHorizontal: "value-horizontal", - valueVertical: "value-vertical", - valueNormal: "value-normal", - valueLarge: "value-large", - valueSub: "value-sub", - }; - // Namespaces of internal event listeners - var INTERNAL_EVENT_NS = { - tooltips: ".__tooltips", - aria: ".__aria", - }; - //endregion - function testStep(parsed, entry) { - if (!isNumeric(entry)) { - throw new Error("noUiSlider: 'step' is not numeric."); - } - // The step option can still be used to set stepping - // for linear sliders. Overwritten if set in 'range'. - parsed.singleStep = entry; - } - function testKeyboardPageMultiplier(parsed, entry) { - if (!isNumeric(entry)) { - throw new Error("noUiSlider: 'keyboardPageMultiplier' is not numeric."); - } - parsed.keyboardPageMultiplier = entry; - } - function testKeyboardMultiplier(parsed, entry) { - if (!isNumeric(entry)) { - throw new Error("noUiSlider: 'keyboardMultiplier' is not numeric."); - } - parsed.keyboardMultiplier = entry; - } - function testKeyboardDefaultStep(parsed, entry) { - if (!isNumeric(entry)) { - throw new Error("noUiSlider: 'keyboardDefaultStep' is not numeric."); - } - parsed.keyboardDefaultStep = entry; - } - function testRange(parsed, entry) { - // Filter incorrect input. - if (typeof entry !== "object" || Array.isArray(entry)) { - throw new Error("noUiSlider: 'range' is not an object."); - } - // Catch missing start or end. - if (entry.min === undefined || entry.max === undefined) { - throw new Error("noUiSlider: Missing 'min' or 'max' in 'range'."); - } - parsed.spectrum = new Spectrum(entry, parsed.snap || false, parsed.singleStep); - } - function testStart(parsed, entry) { - entry = asArray(entry); - // Validate input. Values aren't tested, as the public .val method - // will always provide a valid location. - if (!Array.isArray(entry) || !entry.length) { - throw new Error("noUiSlider: 'start' option is incorrect."); - } - // Store the number of handles. - parsed.handles = entry.length; - // When the slider is initialized, the .val method will - // be called with the start options. - parsed.start = entry; - } - function testSnap(parsed, entry) { - if (typeof entry !== "boolean") { - throw new Error("noUiSlider: 'snap' option must be a boolean."); - } - // Enforce 100% stepping within subranges. - parsed.snap = entry; - } - function testAnimate(parsed, entry) { - if (typeof entry !== "boolean") { - throw new Error("noUiSlider: 'animate' option must be a boolean."); - } - // Enforce 100% stepping within subranges. - parsed.animate = entry; - } - function testAnimationDuration(parsed, entry) { - if (typeof entry !== "number") { - throw new Error("noUiSlider: 'animationDuration' option must be a number."); - } - parsed.animationDuration = entry; - } - function testConnect(parsed, entry) { - var connect = [false]; - var i; - // Map legacy options - if (entry === "lower") { - entry = [true, false]; - } - else if (entry === "upper") { - entry = [false, true]; - } - // Handle boolean options - if (entry === true || entry === false) { - for (i = 1; i < parsed.handles; i++) { - connect.push(entry); - } - connect.push(false); - } - // Reject invalid input - else if (!Array.isArray(entry) || !entry.length || entry.length !== parsed.handles + 1) { - throw new Error("noUiSlider: 'connect' option doesn't match handle count."); - } - else { - connect = entry; - } - parsed.connect = connect; - } - function testOrientation(parsed, entry) { - // Set orientation to an a numerical value for easy - // array selection. - switch (entry) { - case "horizontal": - parsed.ort = 0; - break; - case "vertical": - parsed.ort = 1; - break; - default: - throw new Error("noUiSlider: 'orientation' option is invalid."); - } - } - function testMargin(parsed, entry) { - if (!isNumeric(entry)) { - throw new Error("noUiSlider: 'margin' option must be numeric."); - } - // Issue #582 - if (entry === 0) { - return; - } - parsed.margin = parsed.spectrum.getDistance(entry); - } - function testLimit(parsed, entry) { - if (!isNumeric(entry)) { - throw new Error("noUiSlider: 'limit' option must be numeric."); - } - parsed.limit = parsed.spectrum.getDistance(entry); - if (!parsed.limit || parsed.handles < 2) { - throw new Error("noUiSlider: 'limit' option is only supported on linear sliders with 2 or more handles."); - } - } - function testPadding(parsed, entry) { - var index; - if (!isNumeric(entry) && !Array.isArray(entry)) { - throw new Error("noUiSlider: 'padding' option must be numeric or array of exactly 2 numbers."); - } - if (Array.isArray(entry) && !(entry.length === 2 || isNumeric(entry[0]) || isNumeric(entry[1]))) { - throw new Error("noUiSlider: 'padding' option must be numeric or array of exactly 2 numbers."); - } - if (entry === 0) { - return; - } - if (!Array.isArray(entry)) { - entry = [entry, entry]; - } - // 'getDistance' returns false for invalid values. - parsed.padding = [parsed.spectrum.getDistance(entry[0]), parsed.spectrum.getDistance(entry[1])]; - for (index = 0; index < parsed.spectrum.xNumSteps.length - 1; index++) { - // last "range" can't contain step size as it is purely an endpoint. - if (parsed.padding[0][index] < 0 || parsed.padding[1][index] < 0) { - throw new Error("noUiSlider: 'padding' option must be a positive number(s)."); - } - } - var totalPadding = entry[0] + entry[1]; - var firstValue = parsed.spectrum.xVal[0]; - var lastValue = parsed.spectrum.xVal[parsed.spectrum.xVal.length - 1]; - if (totalPadding / (lastValue - firstValue) > 1) { - throw new Error("noUiSlider: 'padding' option must not exceed 100% of the range."); - } - } - function testDirection(parsed, entry) { - // Set direction as a numerical value for easy parsing. - // Invert connection for RTL sliders, so that the proper - // handles get the connect/background classes. - switch (entry) { - case "ltr": - parsed.dir = 0; - break; - case "rtl": - parsed.dir = 1; - break; - default: - throw new Error("noUiSlider: 'direction' option was not recognized."); - } - } - function testBehaviour(parsed, entry) { - // Make sure the input is a string. - if (typeof entry !== "string") { - throw new Error("noUiSlider: 'behaviour' must be a string containing options."); - } - // Check if the string contains any keywords. - // None are required. - var tap = entry.indexOf("tap") >= 0; - var drag = entry.indexOf("drag") >= 0; - var fixed = entry.indexOf("fixed") >= 0; - var snap = entry.indexOf("snap") >= 0; - var hover = entry.indexOf("hover") >= 0; - var unconstrained = entry.indexOf("unconstrained") >= 0; - var dragAll = entry.indexOf("drag-all") >= 0; - var smoothSteps = entry.indexOf("smooth-steps") >= 0; - if (fixed) { - if (parsed.handles !== 2) { - throw new Error("noUiSlider: 'fixed' behaviour must be used with 2 handles"); - } - // Use margin to enforce fixed state - testMargin(parsed, parsed.start[1] - parsed.start[0]); - } - if (unconstrained && (parsed.margin || parsed.limit)) { - throw new Error("noUiSlider: 'unconstrained' behaviour cannot be used with margin or limit"); - } - parsed.events = { - tap: tap || snap, - drag: drag, - dragAll: dragAll, - smoothSteps: smoothSteps, - fixed: fixed, - snap: snap, - hover: hover, - unconstrained: unconstrained, - }; - } - function testTooltips(parsed, entry) { - if (entry === false) { - return; - } - if (entry === true || isValidPartialFormatter(entry)) { - parsed.tooltips = []; - for (var i = 0; i < parsed.handles; i++) { - parsed.tooltips.push(entry); - } - } - else { - entry = asArray(entry); - if (entry.length !== parsed.handles) { - throw new Error("noUiSlider: must pass a formatter for all handles."); - } - entry.forEach(function (formatter) { - if (typeof formatter !== "boolean" && !isValidPartialFormatter(formatter)) { - throw new Error("noUiSlider: 'tooltips' must be passed a formatter or 'false'."); - } - }); - parsed.tooltips = entry; - } - } - function testHandleAttributes(parsed, entry) { - if (entry.length !== parsed.handles) { - throw new Error("noUiSlider: must pass a attributes for all handles."); - } - parsed.handleAttributes = entry; - } - function testAriaFormat(parsed, entry) { - if (!isValidPartialFormatter(entry)) { - throw new Error("noUiSlider: 'ariaFormat' requires 'to' method."); - } - parsed.ariaFormat = entry; - } - function testFormat(parsed, entry) { - if (!isValidFormatter(entry)) { - throw new Error("noUiSlider: 'format' requires 'to' and 'from' methods."); - } - parsed.format = entry; - } - function testKeyboardSupport(parsed, entry) { - if (typeof entry !== "boolean") { - throw new Error("noUiSlider: 'keyboardSupport' option must be a boolean."); - } - parsed.keyboardSupport = entry; - } - function testDocumentElement(parsed, entry) { - // This is an advanced option. Passed values are used without validation. - parsed.documentElement = entry; - } - function testCssPrefix(parsed, entry) { - if (typeof entry !== "string" && entry !== false) { - throw new Error("noUiSlider: 'cssPrefix' must be a string or `false`."); - } - parsed.cssPrefix = entry; - } - function testCssClasses(parsed, entry) { - if (typeof entry !== "object") { - throw new Error("noUiSlider: 'cssClasses' must be an object."); - } - if (typeof parsed.cssPrefix === "string") { - parsed.cssClasses = {}; - Object.keys(entry).forEach(function (key) { - parsed.cssClasses[key] = parsed.cssPrefix + entry[key]; - }); - } - else { - parsed.cssClasses = entry; - } - } - // Test all developer settings and parse to assumption-safe values. - function testOptions(options) { - // To prove a fix for #537, freeze options here. - // If the object is modified, an error will be thrown. - // Object.freeze(options); - var parsed = { - margin: null, - limit: null, - padding: null, - animate: true, - animationDuration: 300, - ariaFormat: defaultFormatter, - format: defaultFormatter, - }; - // Tests are executed in the order they are presented here. - var tests = { - step: { r: false, t: testStep }, - keyboardPageMultiplier: { r: false, t: testKeyboardPageMultiplier }, - keyboardMultiplier: { r: false, t: testKeyboardMultiplier }, - keyboardDefaultStep: { r: false, t: testKeyboardDefaultStep }, - start: { r: true, t: testStart }, - connect: { r: true, t: testConnect }, - direction: { r: true, t: testDirection }, - snap: { r: false, t: testSnap }, - animate: { r: false, t: testAnimate }, - animationDuration: { r: false, t: testAnimationDuration }, - range: { r: true, t: testRange }, - orientation: { r: false, t: testOrientation }, - margin: { r: false, t: testMargin }, - limit: { r: false, t: testLimit }, - padding: { r: false, t: testPadding }, - behaviour: { r: true, t: testBehaviour }, - ariaFormat: { r: false, t: testAriaFormat }, - format: { r: false, t: testFormat }, - tooltips: { r: false, t: testTooltips }, - keyboardSupport: { r: true, t: testKeyboardSupport }, - documentElement: { r: false, t: testDocumentElement }, - cssPrefix: { r: true, t: testCssPrefix }, - cssClasses: { r: true, t: testCssClasses }, - handleAttributes: { r: false, t: testHandleAttributes }, - }; - var defaults = { - connect: false, - direction: "ltr", - behaviour: "tap", - orientation: "horizontal", - keyboardSupport: true, - cssPrefix: "noUi-", - cssClasses: cssClasses, - keyboardPageMultiplier: 5, - keyboardMultiplier: 1, - keyboardDefaultStep: 10, - }; - // AriaFormat defaults to regular format, if any. - if (options.format && !options.ariaFormat) { - options.ariaFormat = options.format; - } - // Run all options through a testing mechanism to ensure correct - // input. It should be noted that options might get modified to - // be handled properly. E.g. wrapping integers in arrays. - Object.keys(tests).forEach(function (name) { - // If the option isn't set, but it is required, throw an error. - if (!isSet(options[name]) && defaults[name] === undefined) { - if (tests[name].r) { - throw new Error("noUiSlider: '" + name + "' is required."); - } - return; - } - tests[name].t(parsed, !isSet(options[name]) ? defaults[name] : options[name]); - }); - // Forward pips options - parsed.pips = options.pips; - // All recent browsers accept unprefixed transform. - // We need -ms- for IE9 and -webkit- for older Android; - // Assume use of -webkit- if unprefixed and -ms- are not supported. - // https://caniuse.com/#feat=transforms2d - var d = document.createElement("div"); - var msPrefix = d.style.msTransform !== undefined; - var noPrefix = d.style.transform !== undefined; - parsed.transformRule = noPrefix ? "transform" : msPrefix ? "msTransform" : "webkitTransform"; - // Pips don't move, so we can place them using left/top. - var styles = [ - ["left", "top"], - ["right", "bottom"], - ]; - parsed.style = styles[parsed.dir][parsed.ort]; - return parsed; - } - //endregion - function scope(target, options, originalOptions) { - var actions = getActions(); - var supportsTouchActionNone = getSupportsTouchActionNone(); - var supportsPassive = supportsTouchActionNone && getSupportsPassive(); - // All variables local to 'scope' are prefixed with 'scope_' - // Slider DOM Nodes - var scope_Target = target; - var scope_Base; - var scope_Handles; - var scope_Connects; - var scope_Pips; - var scope_Tooltips; - // Slider state values - var scope_Spectrum = options.spectrum; - var scope_Values = []; - var scope_Locations = []; - var scope_HandleNumbers = []; - var scope_ActiveHandlesCount = 0; - var scope_Events = {}; - // Document Nodes - var scope_Document = target.ownerDocument; - var scope_DocumentElement = options.documentElement || scope_Document.documentElement; - var scope_Body = scope_Document.body; - // For horizontal sliders in standard ltr documents, - // make .noUi-origin overflow to the left so the document doesn't scroll. - var scope_DirOffset = scope_Document.dir === "rtl" || options.ort === 1 ? 0 : 100; - // Creates a node, adds it to target, returns the new node. - function addNodeTo(addTarget, className) { - var div = scope_Document.createElement("div"); - if (className) { - addClass(div, className); - } - addTarget.appendChild(div); - return div; - } - // Append a origin to the base - function addOrigin(base, handleNumber) { - var origin = addNodeTo(base, options.cssClasses.origin); - var handle = addNodeTo(origin, options.cssClasses.handle); - addNodeTo(handle, options.cssClasses.touchArea); - handle.setAttribute("data-handle", String(handleNumber)); - if (options.keyboardSupport) { - // https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex - // 0 = focusable and reachable - handle.setAttribute("tabindex", "0"); - handle.addEventListener("keydown", function (event) { - return eventKeydown(event, handleNumber); - }); - } - if (options.handleAttributes !== undefined) { - var attributes_1 = options.handleAttributes[handleNumber]; - Object.keys(attributes_1).forEach(function (attribute) { - handle.setAttribute(attribute, attributes_1[attribute]); - }); - } - handle.setAttribute("role", "slider"); - handle.setAttribute("aria-orientation", options.ort ? "vertical" : "horizontal"); - if (handleNumber === 0) { - addClass(handle, options.cssClasses.handleLower); - } - else if (handleNumber === options.handles - 1) { - addClass(handle, options.cssClasses.handleUpper); - } - return origin; - } - // Insert nodes for connect elements - function addConnect(base, add) { - if (!add) { - return false; - } - return addNodeTo(base, options.cssClasses.connect); - } - // Add handles to the slider base. - function addElements(connectOptions, base) { - var connectBase = addNodeTo(base, options.cssClasses.connects); - scope_Handles = []; - scope_Connects = []; - scope_Connects.push(addConnect(connectBase, connectOptions[0])); - // [::::O====O====O====] - // connectOptions = [0, 1, 1, 1] - for (var i = 0; i < options.handles; i++) { - // Keep a list of all added handles. - scope_Handles.push(addOrigin(base, i)); - scope_HandleNumbers[i] = i; - scope_Connects.push(addConnect(connectBase, connectOptions[i + 1])); - } - } - // Initialize a single slider. - function addSlider(addTarget) { - // Apply classes and data to the target. - addClass(addTarget, options.cssClasses.target); - if (options.dir === 0) { - addClass(addTarget, options.cssClasses.ltr); - } - else { - addClass(addTarget, options.cssClasses.rtl); - } - if (options.ort === 0) { - addClass(addTarget, options.cssClasses.horizontal); - } - else { - addClass(addTarget, options.cssClasses.vertical); - } - var textDirection = getComputedStyle(addTarget).direction; - if (textDirection === "rtl") { - addClass(addTarget, options.cssClasses.textDirectionRtl); - } - else { - addClass(addTarget, options.cssClasses.textDirectionLtr); - } - return addNodeTo(addTarget, options.cssClasses.base); - } - function addTooltip(handle, handleNumber) { - if (!options.tooltips || !options.tooltips[handleNumber]) { - return false; - } - return addNodeTo(handle.firstChild, options.cssClasses.tooltip); - } - function isSliderDisabled() { - return scope_Target.hasAttribute("disabled"); - } - // Disable the slider dragging if any handle is disabled - function isHandleDisabled(handleNumber) { - var handleOrigin = scope_Handles[handleNumber]; - return handleOrigin.hasAttribute("disabled"); - } - function removeTooltips() { - if (scope_Tooltips) { - removeEvent("update" + INTERNAL_EVENT_NS.tooltips); - scope_Tooltips.forEach(function (tooltip) { - if (tooltip) { - removeElement(tooltip); - } - }); - scope_Tooltips = null; - } - } - // The tooltips option is a shorthand for using the 'update' event. - function tooltips() { - removeTooltips(); - // Tooltips are added with options.tooltips in original order. - scope_Tooltips = scope_Handles.map(addTooltip); - bindEvent("update" + INTERNAL_EVENT_NS.tooltips, function (values, handleNumber, unencoded) { - if (!scope_Tooltips || !options.tooltips) { - return; - } - if (scope_Tooltips[handleNumber] === false) { - return; - } - var formattedValue = values[handleNumber]; - if (options.tooltips[handleNumber] !== true) { - formattedValue = options.tooltips[handleNumber].to(unencoded[handleNumber]); - } - scope_Tooltips[handleNumber].innerHTML = formattedValue; - }); - } - function aria() { - removeEvent("update" + INTERNAL_EVENT_NS.aria); - bindEvent("update" + INTERNAL_EVENT_NS.aria, function (values, handleNumber, unencoded, tap, positions) { - // Update Aria Values for all handles, as a change in one changes min and max values for the next. - scope_HandleNumbers.forEach(function (index) { - var handle = scope_Handles[index]; - var min = checkHandlePosition(scope_Locations, index, 0, true, true, true); - var max = checkHandlePosition(scope_Locations, index, 100, true, true, true); - var now = positions[index]; - // Formatted value for display - var text = String(options.ariaFormat.to(unencoded[index])); - // Map to slider range values - min = scope_Spectrum.fromStepping(min).toFixed(1); - max = scope_Spectrum.fromStepping(max).toFixed(1); - now = scope_Spectrum.fromStepping(now).toFixed(1); - handle.children[0].setAttribute("aria-valuemin", min); - handle.children[0].setAttribute("aria-valuemax", max); - handle.children[0].setAttribute("aria-valuenow", now); - handle.children[0].setAttribute("aria-valuetext", text); - }); - }); - } - function getGroup(pips) { - // Use the range. - if (pips.mode === exports.PipsMode.Range || pips.mode === exports.PipsMode.Steps) { - return scope_Spectrum.xVal; - } - if (pips.mode === exports.PipsMode.Count) { - if (pips.values < 2) { - throw new Error("noUiSlider: 'values' (>= 2) required for mode 'count'."); - } - // Divide 0 - 100 in 'count' parts. - var interval = pips.values - 1; - var spread = 100 / interval; - var values = []; - // List these parts and have them handled as 'positions'. - while (interval--) { - values[interval] = interval * spread; - } - values.push(100); - return mapToRange(values, pips.stepped); - } - if (pips.mode === exports.PipsMode.Positions) { - // Map all percentages to on-range values. - return mapToRange(pips.values, pips.stepped); - } - if (pips.mode === exports.PipsMode.Values) { - // If the value must be stepped, it needs to be converted to a percentage first. - if (pips.stepped) { - return pips.values.map(function (value) { - // Convert to percentage, apply step, return to value. - return scope_Spectrum.fromStepping(scope_Spectrum.getStep(scope_Spectrum.toStepping(value))); - }); - } - // Otherwise, we can simply use the values. - return pips.values; - } - return []; // pips.mode = never - } - function mapToRange(values, stepped) { - return values.map(function (value) { - return scope_Spectrum.fromStepping(stepped ? scope_Spectrum.getStep(value) : value); - }); - } - function generateSpread(pips) { - function safeIncrement(value, increment) { - // Avoid floating point variance by dropping the smallest decimal places. - return Number((value + increment).toFixed(7)); - } - var group = getGroup(pips); - var indexes = {}; - var firstInRange = scope_Spectrum.xVal[0]; - var lastInRange = scope_Spectrum.xVal[scope_Spectrum.xVal.length - 1]; - var ignoreFirst = false; - var ignoreLast = false; - var prevPct = 0; - // Create a copy of the group, sort it and filter away all duplicates. - group = unique(group.slice().sort(function (a, b) { - return a - b; - })); - // Make sure the range starts with the first element. - if (group[0] !== firstInRange) { - group.unshift(firstInRange); - ignoreFirst = true; - } - // Likewise for the last one. - if (group[group.length - 1] !== lastInRange) { - group.push(lastInRange); - ignoreLast = true; - } - group.forEach(function (current, index) { - // Get the current step and the lower + upper positions. - var step; - var i; - var q; - var low = current; - var high = group[index + 1]; - var newPct; - var pctDifference; - var pctPos; - var type; - var steps; - var realSteps; - var stepSize; - var isSteps = pips.mode === exports.PipsMode.Steps; - // When using 'steps' mode, use the provided steps. - // Otherwise, we'll step on to the next subrange. - if (isSteps) { - step = scope_Spectrum.xNumSteps[index]; - } - // Default to a 'full' step. - if (!step) { - step = high - low; - } - // If high is undefined we are at the last subrange. Make sure it iterates once (#1088) - if (high === undefined) { - high = low; - } - // Make sure step isn't 0, which would cause an infinite loop (#654) - step = Math.max(step, 0.0000001); - // Find all steps in the subrange. - for (i = low; i <= high; i = safeIncrement(i, step)) { - // Get the percentage value for the current step, - // calculate the size for the subrange. - newPct = scope_Spectrum.toStepping(i); - pctDifference = newPct - prevPct; - steps = pctDifference / (pips.density || 1); - realSteps = Math.round(steps); - // This ratio represents the amount of percentage-space a point indicates. - // For a density 1 the points/percentage = 1. For density 2, that percentage needs to be re-divided. - // Round the percentage offset to an even number, then divide by two - // to spread the offset on both sides of the range. - stepSize = pctDifference / realSteps; - // Divide all points evenly, adding the correct number to this subrange. - // Run up to <= so that 100% gets a point, event if ignoreLast is set. - for (q = 1; q <= realSteps; q += 1) { - // The ratio between the rounded value and the actual size might be ~1% off. - // Correct the percentage offset by the number of points - // per subrange. density = 1 will result in 100 points on the - // full range, 2 for 50, 4 for 25, etc. - pctPos = prevPct + q * stepSize; - indexes[pctPos.toFixed(5)] = [scope_Spectrum.fromStepping(pctPos), 0]; - } - // Determine the point type. - type = group.indexOf(i) > -1 ? exports.PipsType.LargeValue : isSteps ? exports.PipsType.SmallValue : exports.PipsType.NoValue; - // Enforce the 'ignoreFirst' option by overwriting the type for 0. - if (!index && ignoreFirst && i !== high) { - type = 0; - } - if (!(i === high && ignoreLast)) { - // Mark the 'type' of this point. 0 = plain, 1 = real value, 2 = step value. - indexes[newPct.toFixed(5)] = [i, type]; - } - // Update the percentage count. - prevPct = newPct; - } - }); - return indexes; - } - function addMarking(spread, filterFunc, formatter) { - var _a, _b; - var element = scope_Document.createElement("div"); - var valueSizeClasses = (_a = {}, - _a[exports.PipsType.None] = "", - _a[exports.PipsType.NoValue] = options.cssClasses.valueNormal, - _a[exports.PipsType.LargeValue] = options.cssClasses.valueLarge, - _a[exports.PipsType.SmallValue] = options.cssClasses.valueSub, - _a); - var markerSizeClasses = (_b = {}, - _b[exports.PipsType.None] = "", - _b[exports.PipsType.NoValue] = options.cssClasses.markerNormal, - _b[exports.PipsType.LargeValue] = options.cssClasses.markerLarge, - _b[exports.PipsType.SmallValue] = options.cssClasses.markerSub, - _b); - var valueOrientationClasses = [options.cssClasses.valueHorizontal, options.cssClasses.valueVertical]; - var markerOrientationClasses = [options.cssClasses.markerHorizontal, options.cssClasses.markerVertical]; - addClass(element, options.cssClasses.pips); - addClass(element, options.ort === 0 ? options.cssClasses.pipsHorizontal : options.cssClasses.pipsVertical); - function getClasses(type, source) { - var a = source === options.cssClasses.value; - var orientationClasses = a ? valueOrientationClasses : markerOrientationClasses; - var sizeClasses = a ? valueSizeClasses : markerSizeClasses; - return source + " " + orientationClasses[options.ort] + " " + sizeClasses[type]; - } - function addSpread(offset, value, type) { - // Apply the filter function, if it is set. - type = filterFunc ? filterFunc(value, type) : type; - if (type === exports.PipsType.None) { - return; - } - // Add a marker for every point - var node = addNodeTo(element, false); - node.className = getClasses(type, options.cssClasses.marker); - node.style[options.style] = offset + "%"; - // Values are only appended for points marked '1' or '2'. - if (type > exports.PipsType.NoValue) { - node = addNodeTo(element, false); - node.className = getClasses(type, options.cssClasses.value); - node.setAttribute("data-value", String(value)); - node.style[options.style] = offset + "%"; - node.innerHTML = String(formatter.to(value)); - } - } - // Append all points. - Object.keys(spread).forEach(function (offset) { - addSpread(offset, spread[offset][0], spread[offset][1]); - }); - return element; - } - function removePips() { - if (scope_Pips) { - removeElement(scope_Pips); - scope_Pips = null; - } - } - function pips(pips) { - // Fix #669 - removePips(); - var spread = generateSpread(pips); - var filter = pips.filter; - var format = pips.format || { - to: function (value) { - return String(Math.round(value)); - }, - }; - scope_Pips = scope_Target.appendChild(addMarking(spread, filter, format)); - return scope_Pips; - } - // Shorthand for base dimensions. - function baseSize() { - var rect = scope_Base.getBoundingClientRect(); - var alt = ("offset" + ["Width", "Height"][options.ort]); - return options.ort === 0 ? rect.width || scope_Base[alt] : rect.height || scope_Base[alt]; - } - // Handler for attaching events trough a proxy. - function attachEvent(events, element, callback, data) { - // This function can be used to 'filter' events to the slider. - // element is a node, not a nodeList - var method = function (event) { - var e = fixEvent(event, data.pageOffset, data.target || element); - // fixEvent returns false if this event has a different target - // when handling (multi-) touch events; - if (!e) { - return false; - } - // doNotReject is passed by all end events to make sure released touches - // are not rejected, leaving the slider "stuck" to the cursor; - if (isSliderDisabled() && !data.doNotReject) { - return false; - } - // Stop if an active 'tap' transition is taking place. - if (hasClass(scope_Target, options.cssClasses.tap) && !data.doNotReject) { - return false; - } - // Ignore right or middle clicks on start #454 - if (events === actions.start && e.buttons !== undefined && e.buttons > 1) { - return false; - } - // Ignore right or middle clicks on start #454 - if (data.hover && e.buttons) { - return false; - } - // 'supportsPassive' is only true if a browser also supports touch-action: none in CSS. - // iOS safari does not, so it doesn't get to benefit from passive scrolling. iOS does support - // touch-action: manipulation, but that allows panning, which breaks - // sliders after zooming/on non-responsive pages. - // See: https://bugs.webkit.org/show_bug.cgi?id=133112 - if (!supportsPassive) { - e.preventDefault(); - } - e.calcPoint = e.points[options.ort]; - // Call the event handler with the event [ and additional data ]. - callback(e, data); - return; - }; - var methods = []; - // Bind a closure on the target for every event type. - events.split(" ").forEach(function (eventName) { - element.addEventListener(eventName, method, supportsPassive ? { passive: true } : false); - methods.push([eventName, method]); - }); - return methods; - } - // Provide a clean event with standardized offset values. - function fixEvent(e, pageOffset, eventTarget) { - // Filter the event to register the type, which can be - // touch, mouse or pointer. Offset changes need to be - // made on an event specific basis. - var touch = e.type.indexOf("touch") === 0; - var mouse = e.type.indexOf("mouse") === 0; - var pointer = e.type.indexOf("pointer") === 0; - var x = 0; - var y = 0; - // IE10 implemented pointer events with a prefix; - if (e.type.indexOf("MSPointer") === 0) { - pointer = true; - } - // Erroneous events seem to be passed in occasionally on iOS/iPadOS after user finishes interacting with - // the slider. They appear to be of type MouseEvent, yet they don't have usual properties set. Ignore - // events that have no touches or buttons associated with them. (#1057, #1079, #1095) - if (e.type === "mousedown" && !e.buttons && !e.touches) { - return false; - } - // The only thing one handle should be concerned about is the touches that originated on top of it. - if (touch) { - // Returns true if a touch originated on the target. - var isTouchOnTarget = function (checkTouch) { - var target = checkTouch.target; - return (target === eventTarget || - eventTarget.contains(target) || - (e.composed && e.composedPath().shift() === eventTarget)); - }; - // In the case of touchstart events, we need to make sure there is still no more than one - // touch on the target so we look amongst all touches. - if (e.type === "touchstart") { - var targetTouches = Array.prototype.filter.call(e.touches, isTouchOnTarget); - // Do not support more than one touch per handle. - if (targetTouches.length > 1) { - return false; - } - x = targetTouches[0].pageX; - y = targetTouches[0].pageY; - } - else { - // In the other cases, find on changedTouches is enough. - var targetTouch = Array.prototype.find.call(e.changedTouches, isTouchOnTarget); - // Cancel if the target touch has not moved. - if (!targetTouch) { - return false; - } - x = targetTouch.pageX; - y = targetTouch.pageY; - } - } - pageOffset = pageOffset || getPageOffset(scope_Document); - if (mouse || pointer) { - x = e.clientX + pageOffset.x; - y = e.clientY + pageOffset.y; - } - e.pageOffset = pageOffset; - e.points = [x, y]; - e.cursor = mouse || pointer; // Fix #435 - return e; - } - // Translate a coordinate in the document to a percentage on the slider - function calcPointToPercentage(calcPoint) { - var location = calcPoint - offset(scope_Base, options.ort); - var proposal = (location * 100) / baseSize(); - // Clamp proposal between 0% and 100% - // Out-of-bound coordinates may occur when .noUi-base pseudo-elements - // are used (e.g. contained handles feature) - proposal = limit(proposal); - return options.dir ? 100 - proposal : proposal; - } - // Find handle closest to a certain percentage on the slider - function getClosestHandle(clickedPosition) { - var smallestDifference = 100; - var handleNumber = false; - scope_Handles.forEach(function (handle, index) { - // Disabled handles are ignored - if (isHandleDisabled(index)) { - return; - } - var handlePosition = scope_Locations[index]; - var differenceWithThisHandle = Math.abs(handlePosition - clickedPosition); - // Initial state - var clickAtEdge = differenceWithThisHandle === 100 && smallestDifference === 100; - // Difference with this handle is smaller than the previously checked handle - var isCloser = differenceWithThisHandle < smallestDifference; - var isCloserAfter = differenceWithThisHandle <= smallestDifference && clickedPosition > handlePosition; - if (isCloser || isCloserAfter || clickAtEdge) { - handleNumber = index; - smallestDifference = differenceWithThisHandle; - } - }); - return handleNumber; - } - // Fire 'end' when a mouse or pen leaves the document. - function documentLeave(event, data) { - if (event.type === "mouseout" && - event.target.nodeName === "HTML" && - event.relatedTarget === null) { - eventEnd(event, data); - } - } - // Handle movement on document for handle and range drag. - function eventMove(event, data) { - // Fix #498 - // Check value of .buttons in 'start' to work around a bug in IE10 mobile (data.buttonsProperty). - // https://connect.microsoft.com/IE/feedback/details/927005/mobile-ie10-windows-phone-buttons-property-of-pointermove-event-always-zero - // IE9 has .buttons and .which zero on mousemove. - // Firefox breaks the spec MDN defines. - if (navigator.appVersion.indexOf("MSIE 9") === -1 && event.buttons === 0 && data.buttonsProperty !== 0) { - return eventEnd(event, data); - } - // Check if we are moving up or down - var movement = (options.dir ? -1 : 1) * (event.calcPoint - data.startCalcPoint); - // Convert the movement into a percentage of the slider width/height - var proposal = (movement * 100) / data.baseSize; - moveHandles(movement > 0, proposal, data.locations, data.handleNumbers, data.connect); - } - // Unbind move events on document, call callbacks. - function eventEnd(event, data) { - // The handle is no longer active, so remove the class. - if (data.handle) { - removeClass(data.handle, options.cssClasses.active); - scope_ActiveHandlesCount -= 1; - } - // Unbind the move and end events, which are added on 'start'. - data.listeners.forEach(function (c) { - scope_DocumentElement.removeEventListener(c[0], c[1]); - }); - if (scope_ActiveHandlesCount === 0) { - // Remove dragging class. - removeClass(scope_Target, options.cssClasses.drag); - setZindex(); - // Remove cursor styles and text-selection events bound to the body. - if (event.cursor) { - scope_Body.style.cursor = ""; - scope_Body.removeEventListener("selectstart", preventDefault); - } - } - if (options.events.smoothSteps) { - data.handleNumbers.forEach(function (handleNumber) { - setHandle(handleNumber, scope_Locations[handleNumber], true, true, false, false); - }); - data.handleNumbers.forEach(function (handleNumber) { - fireEvent("update", handleNumber); - }); - } - data.handleNumbers.forEach(function (handleNumber) { - fireEvent("change", handleNumber); - fireEvent("set", handleNumber); - fireEvent("end", handleNumber); - }); - } - // Bind move events on document. - function eventStart(event, data) { - // Ignore event if any handle is disabled - if (data.handleNumbers.some(isHandleDisabled)) { - return; - } - var handle; - if (data.handleNumbers.length === 1) { - var handleOrigin = scope_Handles[data.handleNumbers[0]]; - handle = handleOrigin.children[0]; - scope_ActiveHandlesCount += 1; - // Mark the handle as 'active' so it can be styled. - addClass(handle, options.cssClasses.active); - } - // A drag should never propagate up to the 'tap' event. - event.stopPropagation(); - // Record the event listeners. - var listeners = []; - // Attach the move and end events. - var moveEvent = attachEvent(actions.move, scope_DocumentElement, eventMove, { - // The event target has changed so we need to propagate the original one so that we keep - // relying on it to extract target touches. - target: event.target, - handle: handle, - connect: data.connect, - listeners: listeners, - startCalcPoint: event.calcPoint, - baseSize: baseSize(), - pageOffset: event.pageOffset, - handleNumbers: data.handleNumbers, - buttonsProperty: event.buttons, - locations: scope_Locations.slice(), - }); - var endEvent = attachEvent(actions.end, scope_DocumentElement, eventEnd, { - target: event.target, - handle: handle, - listeners: listeners, - doNotReject: true, - handleNumbers: data.handleNumbers, - }); - var outEvent = attachEvent("mouseout", scope_DocumentElement, documentLeave, { - target: event.target, - handle: handle, - listeners: listeners, - doNotReject: true, - handleNumbers: data.handleNumbers, - }); - // We want to make sure we pushed the listeners in the listener list rather than creating - // a new one as it has already been passed to the event handlers. - listeners.push.apply(listeners, moveEvent.concat(endEvent, outEvent)); - // Text selection isn't an issue on touch devices, - // so adding cursor styles can be skipped. - if (event.cursor) { - // Prevent the 'I' cursor and extend the range-drag cursor. - scope_Body.style.cursor = getComputedStyle(event.target).cursor; - // Mark the target with a dragging state. - if (scope_Handles.length > 1) { - addClass(scope_Target, options.cssClasses.drag); - } - // Prevent text selection when dragging the handles. - // In noUiSlider <= 9.2.0, this was handled by calling preventDefault on mouse/touch start/move, - // which is scroll blocking. The selectstart event is supported by FireFox starting from version 52, - // meaning the only holdout is iOS Safari. This doesn't matter: text selection isn't triggered there. - // The 'cursor' flag is false. - // See: http://caniuse.com/#search=selectstart - scope_Body.addEventListener("selectstart", preventDefault, false); - } - data.handleNumbers.forEach(function (handleNumber) { - fireEvent("start", handleNumber); - }); - } - // Move closest handle to tapped location. - function eventTap(event) { - // The tap event shouldn't propagate up - event.stopPropagation(); - var proposal = calcPointToPercentage(event.calcPoint); - var handleNumber = getClosestHandle(proposal); - // Tackle the case that all handles are 'disabled'. - if (handleNumber === false) { - return; - } - // Flag the slider as it is now in a transitional state. - // Transition takes a configurable amount of ms (default 300). Re-enable the slider after that. - if (!options.events.snap) { - addClassFor(scope_Target, options.cssClasses.tap, options.animationDuration); - } - setHandle(handleNumber, proposal, true, true); - setZindex(); - fireEvent("slide", handleNumber, true); - fireEvent("update", handleNumber, true); - if (!options.events.snap) { - fireEvent("change", handleNumber, true); - fireEvent("set", handleNumber, true); - } - else { - eventStart(event, { handleNumbers: [handleNumber] }); - } - } - // Fires a 'hover' event for a hovered mouse/pen position. - function eventHover(event) { - var proposal = calcPointToPercentage(event.calcPoint); - var to = scope_Spectrum.getStep(proposal); - var value = scope_Spectrum.fromStepping(to); - Object.keys(scope_Events).forEach(function (targetEvent) { - if ("hover" === targetEvent.split(".")[0]) { - scope_Events[targetEvent].forEach(function (callback) { - callback.call(scope_Self, value); - }); - } - }); - } - // Handles keydown on focused handles - // Don't move the document when pressing arrow keys on focused handles - function eventKeydown(event, handleNumber) { - if (isSliderDisabled() || isHandleDisabled(handleNumber)) { - return false; - } - var horizontalKeys = ["Left", "Right"]; - var verticalKeys = ["Down", "Up"]; - var largeStepKeys = ["PageDown", "PageUp"]; - var edgeKeys = ["Home", "End"]; - if (options.dir && !options.ort) { - // On an right-to-left slider, the left and right keys act inverted - horizontalKeys.reverse(); - } - else if (options.ort && !options.dir) { - // On a top-to-bottom slider, the up and down keys act inverted - verticalKeys.reverse(); - largeStepKeys.reverse(); - } - // Strip "Arrow" for IE compatibility. https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key - var key = event.key.replace("Arrow", ""); - var isLargeDown = key === largeStepKeys[0]; - var isLargeUp = key === largeStepKeys[1]; - var isDown = key === verticalKeys[0] || key === horizontalKeys[0] || isLargeDown; - var isUp = key === verticalKeys[1] || key === horizontalKeys[1] || isLargeUp; - var isMin = key === edgeKeys[0]; - var isMax = key === edgeKeys[1]; - if (!isDown && !isUp && !isMin && !isMax) { - return true; - } - event.preventDefault(); - var to; - if (isUp || isDown) { - var direction = isDown ? 0 : 1; - var steps = getNextStepsForHandle(handleNumber); - var step = steps[direction]; - // At the edge of a slider, do nothing - if (step === null) { - return false; - } - // No step set, use the default of 10% of the sub-range - if (step === false) { - step = scope_Spectrum.getDefaultStep(scope_Locations[handleNumber], isDown, options.keyboardDefaultStep); - } - if (isLargeUp || isLargeDown) { - step *= options.keyboardPageMultiplier; - } - else { - step *= options.keyboardMultiplier; - } - // Step over zero-length ranges (#948); - step = Math.max(step, 0.0000001); - // Decrement for down steps - step = (isDown ? -1 : 1) * step; - to = scope_Values[handleNumber] + step; - } - else if (isMax) { - // End key - to = options.spectrum.xVal[options.spectrum.xVal.length - 1]; - } - else { - // Home key - to = options.spectrum.xVal[0]; - } - setHandle(handleNumber, scope_Spectrum.toStepping(to), true, true); - fireEvent("slide", handleNumber); - fireEvent("update", handleNumber); - fireEvent("change", handleNumber); - fireEvent("set", handleNumber); - return false; - } - // Attach events to several slider parts. - function bindSliderEvents(behaviour) { - // Attach the standard drag event to the handles. - if (!behaviour.fixed) { - scope_Handles.forEach(function (handle, index) { - // These events are only bound to the visual handle - // element, not the 'real' origin element. - attachEvent(actions.start, handle.children[0], eventStart, { - handleNumbers: [index], - }); - }); - } - // Attach the tap event to the slider base. - if (behaviour.tap) { - attachEvent(actions.start, scope_Base, eventTap, {}); - } - // Fire hover events - if (behaviour.hover) { - attachEvent(actions.move, scope_Base, eventHover, { - hover: true, - }); - } - // Make the range draggable. - if (behaviour.drag) { - scope_Connects.forEach(function (connect, index) { - if (connect === false || index === 0 || index === scope_Connects.length - 1) { - return; - } - var handleBefore = scope_Handles[index - 1]; - var handleAfter = scope_Handles[index]; - var eventHolders = [connect]; - var handlesToDrag = [handleBefore, handleAfter]; - var handleNumbersToDrag = [index - 1, index]; - addClass(connect, options.cssClasses.draggable); - // When the range is fixed, the entire range can - // be dragged by the handles. The handle in the first - // origin will propagate the start event upward, - // but it needs to be bound manually on the other. - if (behaviour.fixed) { - eventHolders.push(handleBefore.children[0]); - eventHolders.push(handleAfter.children[0]); - } - if (behaviour.dragAll) { - handlesToDrag = scope_Handles; - handleNumbersToDrag = scope_HandleNumbers; - } - eventHolders.forEach(function (eventHolder) { - attachEvent(actions.start, eventHolder, eventStart, { - handles: handlesToDrag, - handleNumbers: handleNumbersToDrag, - connect: connect, - }); - }); - }); - } - } - // Attach an event to this slider, possibly including a namespace - function bindEvent(namespacedEvent, callback) { - scope_Events[namespacedEvent] = scope_Events[namespacedEvent] || []; - scope_Events[namespacedEvent].push(callback); - // If the event bound is 'update,' fire it immediately for all handles. - if (namespacedEvent.split(".")[0] === "update") { - scope_Handles.forEach(function (a, index) { - fireEvent("update", index); - }); - } - } - function isInternalNamespace(namespace) { - return namespace === INTERNAL_EVENT_NS.aria || namespace === INTERNAL_EVENT_NS.tooltips; - } - // Undo attachment of event - function removeEvent(namespacedEvent) { - var event = namespacedEvent && namespacedEvent.split(".")[0]; - var namespace = event ? namespacedEvent.substring(event.length) : namespacedEvent; - Object.keys(scope_Events).forEach(function (bind) { - var tEvent = bind.split(".")[0]; - var tNamespace = bind.substring(tEvent.length); - if ((!event || event === tEvent) && (!namespace || namespace === tNamespace)) { - // only delete protected internal event if intentional - if (!isInternalNamespace(tNamespace) || namespace === tNamespace) { - delete scope_Events[bind]; - } - } - }); - } - // External event handling - function fireEvent(eventName, handleNumber, tap) { - Object.keys(scope_Events).forEach(function (targetEvent) { - var eventType = targetEvent.split(".")[0]; - if (eventName === eventType) { - scope_Events[targetEvent].forEach(function (callback) { - callback.call( - // Use the slider public API as the scope ('this') - scope_Self, - // Return values as array, so arg_1[arg_2] is always valid. - scope_Values.map(options.format.to), - // Handle index, 0 or 1 - handleNumber, - // Un-formatted slider values - scope_Values.slice(), - // Event is fired by tap, true or false - tap || false, - // Left offset of the handle, in relation to the slider - scope_Locations.slice(), - // add the slider public API to an accessible parameter when this is unavailable - scope_Self); - }); - } - }); - } - // Split out the handle positioning logic so the Move event can use it, too - function checkHandlePosition(reference, handleNumber, to, lookBackward, lookForward, getValue, smoothSteps) { - var distance; - // For sliders with multiple handles, limit movement to the other handle. - // Apply the margin option by adding it to the handle positions. - if (scope_Handles.length > 1 && !options.events.unconstrained) { - if (lookBackward && handleNumber > 0) { - distance = scope_Spectrum.getAbsoluteDistance(reference[handleNumber - 1], options.margin, false); - to = Math.max(to, distance); - } - if (lookForward && handleNumber < scope_Handles.length - 1) { - distance = scope_Spectrum.getAbsoluteDistance(reference[handleNumber + 1], options.margin, true); - to = Math.min(to, distance); - } - } - // The limit option has the opposite effect, limiting handles to a - // maximum distance from another. Limit must be > 0, as otherwise - // handles would be unmovable. - if (scope_Handles.length > 1 && options.limit) { - if (lookBackward && handleNumber > 0) { - distance = scope_Spectrum.getAbsoluteDistance(reference[handleNumber - 1], options.limit, false); - to = Math.min(to, distance); - } - if (lookForward && handleNumber < scope_Handles.length - 1) { - distance = scope_Spectrum.getAbsoluteDistance(reference[handleNumber + 1], options.limit, true); - to = Math.max(to, distance); - } - } - // The padding option keeps the handles a certain distance from the - // edges of the slider. Padding must be > 0. - if (options.padding) { - if (handleNumber === 0) { - distance = scope_Spectrum.getAbsoluteDistance(0, options.padding[0], false); - to = Math.max(to, distance); - } - if (handleNumber === scope_Handles.length - 1) { - distance = scope_Spectrum.getAbsoluteDistance(100, options.padding[1], true); - to = Math.min(to, distance); - } - } - if (!smoothSteps) { - to = scope_Spectrum.getStep(to); - } - // Limit percentage to the 0 - 100 range - to = limit(to); - // Return false if handle can't move - if (to === reference[handleNumber] && !getValue) { - return false; - } - return to; - } - // Uses slider orientation to create CSS rules. a = base value; - function inRuleOrder(v, a) { - var o = options.ort; - return (o ? a : v) + ", " + (o ? v : a); - } - // Moves handle(s) by a percentage - // (bool, % to move, [% where handle started, ...], [index in scope_Handles, ...]) - function moveHandles(upward, proposal, locations, handleNumbers, connect) { - var proposals = locations.slice(); - // Store first handle now, so we still have it in case handleNumbers is reversed - var firstHandle = handleNumbers[0]; - var smoothSteps = options.events.smoothSteps; - var b = [!upward, upward]; - var f = [upward, !upward]; - // Copy handleNumbers so we don't change the dataset - handleNumbers = handleNumbers.slice(); - // Check to see which handle is 'leading'. - // If that one can't move the second can't either. - if (upward) { - handleNumbers.reverse(); - } - // Step 1: get the maximum percentage that any of the handles can move - if (handleNumbers.length > 1) { - handleNumbers.forEach(function (handleNumber, o) { - var to = checkHandlePosition(proposals, handleNumber, proposals[handleNumber] + proposal, b[o], f[o], false, smoothSteps); - // Stop if one of the handles can't move. - if (to === false) { - proposal = 0; - } - else { - proposal = to - proposals[handleNumber]; - proposals[handleNumber] = to; - } - }); - } - // If using one handle, check backward AND forward - else { - b = f = [true]; - } - var state = false; - // Step 2: Try to set the handles with the found percentage - handleNumbers.forEach(function (handleNumber, o) { - state = - setHandle(handleNumber, locations[handleNumber] + proposal, b[o], f[o], false, smoothSteps) || state; - }); - // Step 3: If a handle moved, fire events - if (state) { - handleNumbers.forEach(function (handleNumber) { - fireEvent("update", handleNumber); - fireEvent("slide", handleNumber); - }); - // If target is a connect, then fire drag event - if (connect != undefined) { - fireEvent("drag", firstHandle); - } - } - } - // Takes a base value and an offset. This offset is used for the connect bar size. - // In the initial design for this feature, the origin element was 1% wide. - // Unfortunately, a rounding bug in Chrome makes it impossible to implement this feature - // in this manner: https://bugs.chromium.org/p/chromium/issues/detail?id=798223 - function transformDirection(a, b) { - return options.dir ? 100 - a - b : a; - } - // Updates scope_Locations and scope_Values, updates visual state - function updateHandlePosition(handleNumber, to) { - // Update locations. - scope_Locations[handleNumber] = to; - // Convert the value to the slider stepping/range. - scope_Values[handleNumber] = scope_Spectrum.fromStepping(to); - var translation = transformDirection(to, 0) - scope_DirOffset; - var translateRule = "translate(" + inRuleOrder(translation + "%", "0") + ")"; - scope_Handles[handleNumber].style[options.transformRule] = translateRule; - updateConnect(handleNumber); - updateConnect(handleNumber + 1); - } - // Handles before the slider middle are stacked later = higher, - // Handles after the middle later is lower - // [[7] [8] .......... | .......... [5] [4] - function setZindex() { - scope_HandleNumbers.forEach(function (handleNumber) { - var dir = scope_Locations[handleNumber] > 50 ? -1 : 1; - var zIndex = 3 + (scope_Handles.length + dir * handleNumber); - scope_Handles[handleNumber].style.zIndex = String(zIndex); - }); - } - // Test suggested values and apply margin, step. - // if exactInput is true, don't run checkHandlePosition, then the handle can be placed in between steps (#436) - function setHandle(handleNumber, to, lookBackward, lookForward, exactInput, smoothSteps) { - if (!exactInput) { - to = checkHandlePosition(scope_Locations, handleNumber, to, lookBackward, lookForward, false, smoothSteps); - } - if (to === false) { - return false; - } - updateHandlePosition(handleNumber, to); - return true; - } - // Updates style attribute for connect nodes - function updateConnect(index) { - // Skip connects set to false - if (!scope_Connects[index]) { - return; - } - var l = 0; - var h = 100; - if (index !== 0) { - l = scope_Locations[index - 1]; - } - if (index !== scope_Connects.length - 1) { - h = scope_Locations[index]; - } - // We use two rules: - // 'translate' to change the left/top offset; - // 'scale' to change the width of the element; - // As the element has a width of 100%, a translation of 100% is equal to 100% of the parent (.noUi-base) - var connectWidth = h - l; - var translateRule = "translate(" + inRuleOrder(transformDirection(l, connectWidth) + "%", "0") + ")"; - var scaleRule = "scale(" + inRuleOrder(connectWidth / 100, "1") + ")"; - scope_Connects[index].style[options.transformRule] = - translateRule + " " + scaleRule; - } - // Parses value passed to .set method. Returns current value if not parse-able. - function resolveToValue(to, handleNumber) { - // Setting with null indicates an 'ignore'. - // Inputting 'false' is invalid. - if (to === null || to === false || to === undefined) { - return scope_Locations[handleNumber]; - } - // If a formatted number was passed, attempt to decode it. - if (typeof to === "number") { - to = String(to); - } - to = options.format.from(to); - if (to !== false) { - to = scope_Spectrum.toStepping(to); - } - // If parsing the number failed, use the current value. - if (to === false || isNaN(to)) { - return scope_Locations[handleNumber]; - } - return to; - } - // Set the slider value. - function valueSet(input, fireSetEvent, exactInput) { - var values = asArray(input); - var isInit = scope_Locations[0] === undefined; - // Event fires by default - fireSetEvent = fireSetEvent === undefined ? true : fireSetEvent; - // Animation is optional. - // Make sure the initial values were set before using animated placement. - if (options.animate && !isInit) { - addClassFor(scope_Target, options.cssClasses.tap, options.animationDuration); - } - // First pass, without lookAhead but with lookBackward. Values are set from left to right. - scope_HandleNumbers.forEach(function (handleNumber) { - setHandle(handleNumber, resolveToValue(values[handleNumber], handleNumber), true, false, exactInput); - }); - var i = scope_HandleNumbers.length === 1 ? 0 : 1; - // Spread handles evenly across the slider if the range has no size (min=max) - if (isInit && scope_Spectrum.hasNoSize()) { - exactInput = true; - scope_Locations[0] = 0; - if (scope_HandleNumbers.length > 1) { - var space_1 = 100 / (scope_HandleNumbers.length - 1); - scope_HandleNumbers.forEach(function (handleNumber) { - scope_Locations[handleNumber] = handleNumber * space_1; - }); - } - } - // Secondary passes. Now that all base values are set, apply constraints. - // Iterate all handles to ensure constraints are applied for the entire slider (Issue #1009) - for (; i < scope_HandleNumbers.length; ++i) { - scope_HandleNumbers.forEach(function (handleNumber) { - setHandle(handleNumber, scope_Locations[handleNumber], true, true, exactInput); - }); - } - setZindex(); - scope_HandleNumbers.forEach(function (handleNumber) { - fireEvent("update", handleNumber); - // Fire the event only for handles that received a new value, as per #579 - if (values[handleNumber] !== null && fireSetEvent) { - fireEvent("set", handleNumber); - } - }); - } - // Reset slider to initial values - function valueReset(fireSetEvent) { - valueSet(options.start, fireSetEvent); - } - // Set value for a single handle - function valueSetHandle(handleNumber, value, fireSetEvent, exactInput) { - // Ensure numeric input - handleNumber = Number(handleNumber); - if (!(handleNumber >= 0 && handleNumber < scope_HandleNumbers.length)) { - throw new Error("noUiSlider: invalid handle number, got: " + handleNumber); - } - // Look both backward and forward, since we don't want this handle to "push" other handles (#960); - // The exactInput argument can be used to ignore slider stepping (#436) - setHandle(handleNumber, resolveToValue(value, handleNumber), true, true, exactInput); - fireEvent("update", handleNumber); - if (fireSetEvent) { - fireEvent("set", handleNumber); - } - } - // Get the slider value. - function valueGet(unencoded) { - if (unencoded === void 0) { unencoded = false; } - if (unencoded) { - // return a copy of the raw values - return scope_Values.length === 1 ? scope_Values[0] : scope_Values.slice(0); - } - var values = scope_Values.map(options.format.to); - // If only one handle is used, return a single value. - if (values.length === 1) { - return values[0]; - } - return values; - } - // Removes classes from the root and empties it. - function destroy() { - // remove protected internal listeners - removeEvent(INTERNAL_EVENT_NS.aria); - removeEvent(INTERNAL_EVENT_NS.tooltips); - Object.keys(options.cssClasses).forEach(function (key) { - removeClass(scope_Target, options.cssClasses[key]); - }); - while (scope_Target.firstChild) { - scope_Target.removeChild(scope_Target.firstChild); - } - delete scope_Target.noUiSlider; - } - function getNextStepsForHandle(handleNumber) { - var location = scope_Locations[handleNumber]; - var nearbySteps = scope_Spectrum.getNearbySteps(location); - var value = scope_Values[handleNumber]; - var increment = nearbySteps.thisStep.step; - var decrement = null; - // If snapped, directly use defined step value - if (options.snap) { - return [ - value - nearbySteps.stepBefore.startValue || null, - nearbySteps.stepAfter.startValue - value || null, - ]; - } - // If the next value in this step moves into the next step, - // the increment is the start of the next step - the current value - if (increment !== false) { - if (value + increment > nearbySteps.stepAfter.startValue) { - increment = nearbySteps.stepAfter.startValue - value; - } - } - // If the value is beyond the starting point - if (value > nearbySteps.thisStep.startValue) { - decrement = nearbySteps.thisStep.step; - } - else if (nearbySteps.stepBefore.step === false) { - decrement = false; - } - // If a handle is at the start of a step, it always steps back into the previous step first - else { - decrement = value - nearbySteps.stepBefore.highestStep; - } - // Now, if at the slider edges, there is no in/decrement - if (location === 100) { - increment = null; - } - else if (location === 0) { - decrement = null; - } - // As per #391, the comparison for the decrement step can have some rounding issues. - var stepDecimals = scope_Spectrum.countStepDecimals(); - // Round per #391 - if (increment !== null && increment !== false) { - increment = Number(increment.toFixed(stepDecimals)); - } - if (decrement !== null && decrement !== false) { - decrement = Number(decrement.toFixed(stepDecimals)); - } - return [decrement, increment]; - } - // Get the current step size for the slider. - function getNextSteps() { - return scope_HandleNumbers.map(getNextStepsForHandle); - } - // Updatable: margin, limit, padding, step, range, animate, snap - function updateOptions(optionsToUpdate, fireSetEvent) { - // Spectrum is created using the range, snap, direction and step options. - // 'snap' and 'step' can be updated. - // If 'snap' and 'step' are not passed, they should remain unchanged. - var v = valueGet(); - var updateAble = [ - "margin", - "limit", - "padding", - "range", - "animate", - "snap", - "step", - "format", - "pips", - "tooltips", - ]; - // Only change options that we're actually passed to update. - updateAble.forEach(function (name) { - // Check for undefined. null removes the value. - if (optionsToUpdate[name] !== undefined) { - originalOptions[name] = optionsToUpdate[name]; - } - }); - var newOptions = testOptions(originalOptions); - // Load new options into the slider state - updateAble.forEach(function (name) { - if (optionsToUpdate[name] !== undefined) { - options[name] = newOptions[name]; - } - }); - scope_Spectrum = newOptions.spectrum; - // Limit, margin and padding depend on the spectrum but are stored outside of it. (#677) - options.margin = newOptions.margin; - options.limit = newOptions.limit; - options.padding = newOptions.padding; - // Update pips, removes existing. - if (options.pips) { - pips(options.pips); - } - else { - removePips(); - } - // Update tooltips, removes existing. - if (options.tooltips) { - tooltips(); - } - else { - removeTooltips(); - } - // Invalidate the current positioning so valueSet forces an update. - scope_Locations = []; - valueSet(isSet(optionsToUpdate.start) ? optionsToUpdate.start : v, fireSetEvent); - } - // Initialization steps - function setupSlider() { - // Create the base element, initialize HTML and set classes. - // Add handles and connect elements. - scope_Base = addSlider(scope_Target); - addElements(options.connect, scope_Base); - // Attach user events. - bindSliderEvents(options.events); - // Use the public value method to set the start values. - valueSet(options.start); - if (options.pips) { - pips(options.pips); - } - if (options.tooltips) { - tooltips(); - } - aria(); - } - setupSlider(); - var scope_Self = { - destroy: destroy, - steps: getNextSteps, - on: bindEvent, - off: removeEvent, - get: valueGet, - set: valueSet, - setHandle: valueSetHandle, - reset: valueReset, - // Exposed for unit testing, don't use this in your application. - __moveHandles: function (upward, proposal, handleNumbers) { - moveHandles(upward, proposal, scope_Locations, handleNumbers); - }, - options: originalOptions, - updateOptions: updateOptions, - target: scope_Target, - removePips: removePips, - removeTooltips: removeTooltips, - getPositions: function () { - return scope_Locations.slice(); - }, - getTooltips: function () { - return scope_Tooltips; - }, - getOrigins: function () { - return scope_Handles; - }, - pips: pips, // Issue #594 - }; - return scope_Self; - } - // Run the standard initializer - function initialize(target, originalOptions) { - if (!target || !target.nodeName) { - throw new Error("noUiSlider: create requires a single element, got: " + target); - } - // Throw an error if the slider was already initialized. - if (target.noUiSlider) { - throw new Error("noUiSlider: Slider was already initialized."); - } - // Test the options and create the slider environment; - var options = testOptions(originalOptions); - var api = scope(target, options, originalOptions); - target.noUiSlider = api; - return api; - } - var nouislider = { - // Exposed for unit testing, don't use this in your application. - __spectrum: Spectrum, - // A reference to the default classes, allows global changes. - // Use the cssClasses option for changes to one slider. - cssClasses: cssClasses, - create: initialize, - }; - - exports.create = initialize; - exports.cssClasses = cssClasses; - exports["default"] = nouislider; - - Object.defineProperty(exports, '__esModule', { value: true }); - -})); diff --git a/src/assets/lib/nouislider/nouislider.min.css b/src/assets/lib/nouislider/nouislider.min.css deleted file mode 100644 index 60f217c0..00000000 --- a/src/assets/lib/nouislider/nouislider.min.css +++ /dev/null @@ -1 +0,0 @@ -.noUi-target,.noUi-target *{-webkit-touch-callout:none;-webkit-tap-highlight-color:transparent;-webkit-user-select:none;-ms-touch-action:none;touch-action:none;-ms-user-select:none;-moz-user-select:none;user-select:none;-moz-box-sizing:border-box;box-sizing:border-box}.noUi-target{position:relative}.noUi-base,.noUi-connects{width:100%;height:100%;position:relative;z-index:1}.noUi-connects{overflow:hidden;z-index:0}.noUi-connect,.noUi-origin{will-change:transform;position:absolute;z-index:1;top:0;right:0;height:100%;width:100%;-ms-transform-origin:0 0;-webkit-transform-origin:0 0;-webkit-transform-style:preserve-3d;transform-origin:0 0;transform-style:flat}.noUi-txt-dir-rtl.noUi-horizontal .noUi-origin{left:0;right:auto}.noUi-vertical .noUi-origin{top:-100%;width:0}.noUi-horizontal .noUi-origin{height:0}.noUi-handle{-webkit-backface-visibility:hidden;backface-visibility:hidden;position:absolute}.noUi-touch-area{height:100%;width:100%}.noUi-state-tap .noUi-connect,.noUi-state-tap .noUi-origin{-webkit-transition:transform .3s;transition:transform .3s}.noUi-state-drag *{cursor:inherit!important}.noUi-horizontal{height:18px}.noUi-horizontal .noUi-handle{width:34px;height:28px;right:-17px;top:-6px}.noUi-vertical{width:18px}.noUi-vertical .noUi-handle{width:28px;height:34px;right:-6px;bottom:-17px}.noUi-txt-dir-rtl.noUi-horizontal .noUi-handle{left:-17px;right:auto}.noUi-target{background:#FAFAFA;border-radius:4px;border:1px solid #D3D3D3;box-shadow:inset 0 1px 1px #F0F0F0,0 3px 6px -5px #BBB}.noUi-connects{border-radius:3px}.noUi-connect{background:#3FB8AF}.noUi-draggable{cursor:ew-resize}.noUi-vertical .noUi-draggable{cursor:ns-resize}.noUi-handle{border:1px solid #D9D9D9;border-radius:3px;background:#FFF;cursor:default;box-shadow:inset 0 0 1px #FFF,inset 0 1px 7px #EBEBEB,0 3px 6px -3px #BBB}.noUi-active{box-shadow:inset 0 0 1px #FFF,inset 0 1px 7px #DDD,0 3px 6px -3px #BBB}.noUi-handle:after,.noUi-handle:before{content:"";display:block;position:absolute;height:14px;width:1px;background:#E8E7E6;left:14px;top:6px}.noUi-handle:after{left:17px}.noUi-vertical .noUi-handle:after,.noUi-vertical .noUi-handle:before{width:14px;height:1px;left:6px;top:14px}.noUi-vertical .noUi-handle:after{top:17px}[disabled] .noUi-connect{background:#B8B8B8}[disabled] .noUi-handle,[disabled].noUi-handle,[disabled].noUi-target{cursor:not-allowed}.noUi-pips,.noUi-pips *{-moz-box-sizing:border-box;box-sizing:border-box}.noUi-pips{position:absolute;color:#999}.noUi-value{position:absolute;white-space:nowrap;text-align:center}.noUi-value-sub{color:#ccc;font-size:10px}.noUi-marker{position:absolute;background:#CCC}.noUi-marker-sub{background:#AAA}.noUi-marker-large{background:#AAA}.noUi-pips-horizontal{padding:10px 0;height:80px;top:100%;left:0;width:100%}.noUi-value-horizontal{-webkit-transform:translate(-50%,50%);transform:translate(-50%,50%)}.noUi-rtl .noUi-value-horizontal{-webkit-transform:translate(50%,50%);transform:translate(50%,50%)}.noUi-marker-horizontal.noUi-marker{margin-left:-1px;width:2px;height:5px}.noUi-marker-horizontal.noUi-marker-sub{height:10px}.noUi-marker-horizontal.noUi-marker-large{height:15px}.noUi-pips-vertical{padding:0 10px;height:100%;top:0;left:100%}.noUi-value-vertical{-webkit-transform:translate(0,-50%);transform:translate(0,-50%);padding-left:25px}.noUi-rtl .noUi-value-vertical{-webkit-transform:translate(0,50%);transform:translate(0,50%)}.noUi-marker-vertical.noUi-marker{width:5px;height:2px;margin-top:-1px}.noUi-marker-vertical.noUi-marker-sub{width:10px}.noUi-marker-vertical.noUi-marker-large{width:15px}.noUi-tooltip{display:block;position:absolute;border:1px solid #D9D9D9;border-radius:3px;background:#fff;color:#000;padding:5px;text-align:center;white-space:nowrap}.noUi-horizontal .noUi-tooltip{-webkit-transform:translate(-50%,0);transform:translate(-50%,0);left:50%;bottom:120%}.noUi-vertical .noUi-tooltip{-webkit-transform:translate(0,-50%);transform:translate(0,-50%);top:50%;right:120%}.noUi-horizontal .noUi-origin>.noUi-tooltip{-webkit-transform:translate(50%,0);transform:translate(50%,0);left:auto;bottom:10px}.noUi-vertical .noUi-origin>.noUi-tooltip{-webkit-transform:translate(0,-18px);transform:translate(0,-18px);top:auto;right:28px} \ No newline at end of file diff --git a/src/assets/technology/CHANNEL.png b/src/assets/technology/CHANNEL.png deleted file mode 100644 index baff7c31..00000000 Binary files a/src/assets/technology/CHANNEL.png and /dev/null differ diff --git a/src/componentAPI.ts b/src/componentAPI.ts deleted file mode 100644 index aaf2edcf..00000000 --- a/src/componentAPI.ts +++ /dev/null @@ -1,534 +0,0 @@ -import Text from "./app/library/text"; -import Port from "./app/library/port"; -import Anode from "./app/library/anode"; // new from CK -import Cathode from "./app/library/cathode"; // new from CK -import Channel from "./app/library/channel"; -import BetterMixer from "./app/library/betterMixer"; -import RotaryMixer from "./app/library/rotaryMixer"; -import AlignmentMarks from "./app/library/alignmentMarks"; -import CellTrapL from "./app/library/celltrapL"; -import Gelchannel from "./app/library/gelchannel"; // CK -import Chamber from "./app/library/chamber"; -import Connection from "./app/library/connection"; -import CurvedMixer from "./app/library/curvedMixer"; -import DiamondReactionChamber from "./app/library/diamondReactionChamber"; -import DropletGenerator from "./app/library/dropletGenerator"; -import GradientGenerator from "./app/library/gradientGenerator"; -import Mux from "./app/library/mux"; -import Pump from "./app/library/pump"; -import Pump3D from "./app/library/pump3D"; -import RoundedChannel from "./app/library/roundedChannel"; -import thermoCycler from "./app/library/thermoCycler"; -import Transition from "./app/library/transition"; -import Transposer from "./app/library/transposer"; -import Valve from "./app/library/valve"; -import Valve3D from "./app/library/valve3D"; -import Tree from "./app/library/tree"; -import YTree from "./app/library/ytree"; -import LLChamber from "./app/library/llChamber"; -import ThreeDMixer from "./app/library/threeDMixer"; -import Via from "./app/library/via"; - -// new - -import Filter from "./app/library/filter"; -import CellTrapS from "./app/library/celltrapS"; -import ThreeDMux from "./app/library/threeDMux"; -import ChemostatRing from "./app/library/chemostatring"; -import Incubation from "./app/library/incubation"; -import Merger from "./app/library/merger"; -import PicoInjection from "./app/library/picoinjection"; -import Sorter from "./app/library/sorter"; -import CapacitanceSensor from "./app/library/capacitancesensor"; -import Splitter from "./app/library/splitter"; -import Node from "./app/library/node"; -import DropletGeneratorT from "./app/library/dropletGeneratorT"; -import DropletGeneratorFlowFocus from "./app/library/dropletGeneratorFlowFocus"; -import LogicArray from "./app/library/logicArray"; -import ToroidalMixer from "./app/library/toroidalMixer"; -import DogboneInsert from "./app/library/dogboneInsert"; - -import Template from "./app/library/template"; -import ComponentPort from "./app/core/componentPort"; -import CustomComponent from "./app/core/customComponent"; -import uuid from "node-uuid"; -import FeatureTemplate from "./app/library/geometricElements/featureTemplate"; -import NormallyClosedValveCrescents from "./app/library/geometricElements/normallyClosedValveCrecents"; -import NormallyClosedValveModificationsGap from "./app/library/geometricElements/normallyClosedValveGap"; -import { ValveType } from "./app/core/init"; - -export var PRIMITIVES_SERVER = false; - -export function enablePrimitiveServer() { - PRIMITIVES_SERVER = true; -} -export type LibraryEntryDefinition = { - unique: { [key: string]: string }; - heritable: { [key: string]: string }; - units: { [key: string]: string }; - defaults: { [key: string]: number }; - minimum: { [key: string]: number }; - maximum: { [key: string]: number }; - mint: string; -}; - -type LibraryEntry = { - object: Template; - key: string; -}; - -type FeatureLibraryEntry = { - object: FeatureTemplate; - key: string; -}; - -/** - * Component API Class that contains all the components and their definitions, - * Replaces the FeatureSet API in the future and simplifies all the extension - * of the library. - * - * @class ComponentAPI - */ -export class ComponentAPI { - static library: { [key: string]: LibraryEntry } = { - Template: { object: new Template(), key: "FLOW" }, - Text: { object: new Text(), key: "FLOW" }, - Port: { object: new Port(), key: "FLOW" }, - Anode: { object: new Anode(), key: "INTEGRATION" }, // ck addition - Cathode: { object: new Cathode(), key: "INTEGRATION" }, // ck addition - Channel: { object: new Channel(), key: "FLOW" }, - BetterMixer: { object: new BetterMixer(), key: "FLOW" }, - RotaryMixer: { object: new RotaryMixer(), key: "FLOW" }, - RotaryMixer_control: { object: new RotaryMixer(), key: "CONTROL" }, - AlignmentMarks: { object: new AlignmentMarks(), key: "FLOW" }, - AlignmentMarks_control: { - object: new AlignmentMarks(), - key: "CONTROL" - }, - CellTrapL: { object: new CellTrapL(), key: "FLOW" }, - CellTrapL_cell: { object: new CellTrapL(), key: "CELL" }, - Gelchannel: { object: new Gelchannel(), key: "FLOW" }, // CK - Gelchannel_cell: { object: new Gelchannel(), key: "CELL" }, // CK - Chamber: { object: new Chamber(), key: "FLOW" }, - CurvedMixer: { object: new CurvedMixer(), key: "FLOW" }, - ToroidalMixer: { object: new ToroidalMixer(), key: "FLOW"}, - DiamondReactionChamber: { - object: new DiamondReactionChamber(), - key: "FLOW" - }, - - Connection: { object: new Connection(), key: "FLOW" }, - DropletGen: { object: new DropletGenerator(), key: "FLOW" }, - GradientGenerator: { object: new GradientGenerator(), key: "FLOW" }, - Mux: { object: new Mux(), key: "FLOW" }, - Mux_control: { object: new Mux(), key: "CONTROL" }, - Pump: { object: new Pump(), key: "FLOW" }, - Pump_control: { object: new Pump(), key: "CONTROL" }, - Pump3D: { object: new Pump3D(), key: "FLOW" }, - Pump3D_control: { object: new Pump3D(), key: "CONTROL" }, - RoundedChannel: { object: new RoundedChannel(), key: "FLOW" }, - thermoCycler: { object: new thermoCycler(), key: "FLOW" }, - Transition: { object: new Transition(), key: "FLOW" }, - Transposer: { object: new Transposer(), key: "FLOW" }, - Transposer_control: { object: new Transposer(), key: "CONTROL" }, - Tree: { object: new Tree(), key: "FLOW" }, - YTree: { object: new YTree(), key: "FLOW" }, - Valve: { object: new Valve(ValveType.NORMALLY_OPEN), key: "CONTROL" }, - // TODO: Get rid of this fully after we move over to the new valve feature system - // Valve3D: { object: new Valve3D(ValveType.NORMALLY_CLOSED), key: "FLOW" }, - Valve3D_control: { object: new Valve3D(ValveType.NORMALLY_CLOSED), key: "CONTROL" }, - LLChamber: { object: new LLChamber(), key: "FLOW" }, - LLChamber_control: { object: new LLChamber(), key: "CONTROL" }, - "3DMixer": { object: new ThreeDMixer(), key: "FLOW" }, - "3DMixer_control": { object: new ThreeDMixer(), key: "CONTROL" }, - Via: { object: new Via(), key: "FLOW" }, - - // new - DogboneInsert: { object: new DogboneInsert(), key: "FLOW" }, - Filter: { object: new Filter(), key: "FLOW" }, - CellTrapS: { object: new CellTrapS(), key: "FLOW" }, - CellTrapS_cell: { object: new CellTrapS(), key: "CELL" }, - "3DMux": { object: new ThreeDMux(), key: "FLOW" }, - "3DMux_control": { object: new ThreeDMux(), key: "CONTROL" }, - ChemostatRing: { object: new ChemostatRing(), key: "FLOW" }, - ChemostatRing_control: { object: new ChemostatRing(), key: "CONTROL" }, - Incubation: { object: new Incubation(), key: "FLOW" }, - Merger: { object: new Merger(), key: "FLOW" }, - Merger_integration: { object: new Merger(), key: "INTEGRATION" }, - PicoInjection: { object: new PicoInjection(), key: "FLOW" }, - PicoInjection_integration: { object: new PicoInjection(), key: "INTEGRATION" }, - Sorter: { object: new Sorter(), key: "FLOW" }, - Sorter_integration: { object: new Sorter(), key: "INTEGRATION" }, - Splitter: { object: new Splitter(), key: "FLOW" }, - CapacitanceSensor: { object: new CapacitanceSensor(), key: "FLOW" }, - CapacitanceSensor_integration: { object: new CapacitanceSensor(), key: "INTEGRATION" }, - Node: { object: new Node(), key: "FLOW" }, - DropletGenT: { object: new DropletGeneratorT(), key: "FLOW" }, - DropletGenFlow: { object: new DropletGeneratorFlowFocus(), key: "FLOW" }, - LogicArray: { object: new LogicArray(), key: "FLOW" }, - LogicArray_control: { object: new LogicArray(), key: "CONTROL" }, - LogicArray_cell: { object: new LogicArray(), key: "CELL" }, - }; - - static connectionLibrary: { [key: string]: LibraryEntry } = { - Connection: { object: new Connection(), key: "FLOW" } - }; - - static featureLibrary: { [key: string]: FeatureLibraryEntry } = { - // Features - NormallyClosedValveModifications: { object: new NormallyClosedValveCrescents(), key: "FLOW" }, - NormallyClosedValveModifications_Gap: { object: new NormallyClosedValveModificationsGap(), key: "GAP" }, - - } - - - static customTypes: Map = new Map(); - __setString: any; - __tools: any; - __render2D: any; - __render3D: any; - name: any; - setString: string | undefined; - - /** - * Gets all the components definitions (template type objects) in the library. - * - * @static - * @returns {Array