source: js/human_3d_alignment/src/visualization/framstick.js @ 944

Last change on this file since 944 was 911, checked in by Maciej Komosinski, 5 years ago

Added the actual functionality of the app in place of previous draft

File size: 6.8 KB
RevLine 
[911]1/*global Module*/
2"use strict";
3
4import * as THREE from 'three';
5import PartMeshFactory from './partmeshfactory';
6import JointMeshFactory from './jointmeshfactory';
7import GenotypeParser from '../utils/genotypeparser';
8import { geometry } from './transformations';
9
10
11/**
12 * @file Framstick Object
13 * @author Patryk Gliszczynski
14 * @version 1.2
15 */
16class Framstick {
17
18  /**
19   *
20   * @param {Genotype} genotype genotype of creating framstick
21   */
22  constructor(genotype, viewer) {
23    this.viewer = viewer;
24    this.genotype = genotype;
25    this.parts = [];
26    this.joints = [];
27    this.meshes = [];
28   
29    this.positions = [];
30    this.color = 'white';
31    this.avgPosition = new THREE.Vector3(0, 0, 0);
32
33    this.partfactory = new PartMeshFactory(geometry.part);
34    this.jointfactory = new JointMeshFactory(geometry.joint);
35
36    this.mesh = new THREE.Group();
37    this.loadFromGenotype();
38
39    for (let i = 0; i < this.mesh.children.length; i++) {
40      this.avgPosition.add(this.mesh.children[i].position.clone());
41    }
42
43    this.avgPosition.divideScalar(this.mesh.children.length);
44
45    for (let i = 0; i < this.mesh.children.length; i++) {
46      this.mesh.children[i].position.sub(this.avgPosition);
47    }
48
49    this.viewer.scene.add(this.mesh);
50
51  }
52
53  /**
54   * Change Framstick's color on click
55   */
56  setColor(color) {
57    if (this.color != color) {
58      let colorTemp = this.color;
59      this.color = color;
60
61      let position = this.mesh.position.clone();
62      let rotation = this.mesh.rotation.clone();
63      this.viewer.scene.remove(this.mesh);
64
65      this.loadFromGenotype();
66
67      this.mesh.position.set( position.x, position.y, position.z );
68      this.mesh.rotation.set(rotation.x, rotation.y, rotation.z, rotation.order );
69
70
71      if (this.color == 'red' || colorTemp == 'red') {
72        for (let i = 0; i < this.meshes.length; i++) {
73          this.viewer.meshes.shift();
74        }
75        for (let i = 0; i < this.parts.length; i++) {
76          this.viewer.parts.shift();
77        }
78        for (let i = this.meshes.length - 1; i >= 0; i--) {
79          this.viewer.meshes.unshift(this.meshes[i]);
80        }
81        for (let i = this.parts.length - 1; i >= 0; i--) {
82          this.viewer.parts.unshift(this.parts[i]);
83        }
84      } else {
85        for (let i = 0; i < this.meshes.length; i++) {
86          this.viewer.meshes.pop();
87        }
88        for (let i = 0; i < this.parts.length; i++) {
89          this.viewer.parts.pop();
90        }
91        for (let i = 0; i < this.meshes.length; i++) {
92          this.viewer.meshes.push(this.meshes[i]);
93        }
94        for (let i = 0; i < this.parts.length; i++) {
95          this.viewer.parts.push(this.parts[i]);
96        }
97      }
98
99      this.viewer.scene.add(this.mesh);
100    }
101  }
102
103  addText(nr) {
104    for (let i = 0; i < this.positions.length; i++) {
105      let div = document.createElement("div");
106      div.className = "label";
107      div.style.position = 'absolute';
108      div.style.color = 'white';
109      div.style.textAlign = 'center';
110      div.style.display = '';
111      div.style.fontFamily = "'Fira Mono', Monaco, 'Andale Mono', 'Lucida Console', 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace";
112      //div.style.margin = '-5px 0 0 15px';
113      div.style.pointerEvents = 'none';
114      div.style.webkitUserSelect = 'none';
115      div.style.mozUserSelect = 'none';
116      div.style.msUserSelect = 'none';
117      div.style.userSelect = 'none';
118
119      if (nr == 1) {
120        div.textContent = (i+1).toString();
121      } else {
122        let label = '';
123        if (i + 1 + 64 > 90) {
124          label = String.fromCharCode(i + 1 + 70);
125        } else {
126          label = String.fromCharCode(i + 1 + 64);
127        }   
128        div.textContent = label;
129      }
130     
131      let pos = new THREE.Vector3().copy(this.positions[i]).applyEuler(this.mesh.rotation).add(this.mesh.position);
132      let dis = pos.distanceTo(this.viewer.camera.perspectiveCamera.position);
133      pos.project(this.viewer.camera.perspectiveCamera);
134
135      this.viewer.raycaster.setFromCamera(pos, this.viewer.camera.perspectiveCamera);
136
137      let intersectedObjects = this.viewer.raycaster.intersectObjects(this.viewer.parts);
138      let show = intersectedObjects.length && this.parts[i] === intersectedObjects[0].object;
139
140
141      if (Math.abs(pos.z) > 1 || pos.x < -0.96 || pos.y < -0.96 || pos.x > 0.96 || pos.y > 0.96)  {
142        div.style.display = 'none';
143      } else {
144        div.style.fontSize = (150.0 / dis).toString() + 'px';
145        div.style.display = '';
146
147        if ((150.0 / dis)/(2*this.viewer.container.clientHeight) + pos.y > 1.0 ||
148            pos.y - (150.0 / dis)/(2*this.viewer.container.clientHeight) < -1.0 ||
149            (150.0 / dis)/(2*this.viewer.container.clientWidth) + pos.x > 1.0 ||
150            pos.x - (150.0 / dis)/(2*this.viewer.container.clientWidth) < -1.0) {
151          div.style.display = 'none';
152        }
153        div.style.zIndex = (-pos.z * .5 + .5) * 100000 | 0;
154
155        if (!show) {
156          //div.style.margin = '-5px 0 0 15px';
157          div.style.display = 'none';
158        }
159       
160        let x = (pos.x *  .5 + .5) * this.viewer.container.clientWidth;
161        let y = (pos.y * -.5 + .5) * this.viewer.container.clientHeight;
162        div.style.transform = `translate(-50%, -50%) translate(${x}px,${y}px)`;
163        this.viewer.container.appendChild(div);
164      }
165
166    }
167  }
168
169  /**
170   * Return framstick position in the world
171   */
172  setPositions() {
173    this.positions = [];
174    let tempV = new THREE.Vector3();
175
176    for (let i = 0; i < this.parts.length; i++) {
177      let mesh = this.parts[i];
178
179      this.viewer.camera.perspectiveCamera.updateMatrixWorld(true, false);
180      mesh.getWorldPosition(tempV);
181      this.positions.push(tempV.clone());
182    }
183  }
184
185  /**
186  * Code below was taken from: http://fugue.synology.me:30000/grzegorzlatosinski/framsticks-js
187  * @author Grzegorz Latosiński
188  * @pull_date 22.01.2018
189  */
190  loadFromGenotype() {
191    this.mesh = new THREE.Group();
192
193    let model = GenotypeParser.getModelFromGenotype(this.genotype);
194
195    if (typeof model !== 'undefined') {
196      let partsforjoints = [];
197      this.meshes = [];
198      this.parts = [];
199      this.joints = [];
200
201      for (let i = 0; i < model.getPartCount(); i++) {
202        let m = this.partfactory.create(model.getPart(i), this.color);
203        partsforjoints.push(m.userData);
204        this.mesh.add(m)
205        this.parts.push(m);
206        this.meshes.push(m);
207      }
208
209      for (let i = 0; i < model.getJointCount(); i++) {
210        let m = this.jointfactory.create(model.getJoint(i), this.color, partsforjoints);
211       
212        this.mesh.add(m);
213        this.joints.push(m);
214        this.meshes.push(m);
215      }
216
217      new THREE.Box3().setFromObject(this.mesh).getCenter(this.mesh.position).multiplyScalar(-1);
218
219      for (let i = 0; i < this.mesh.children.length; i++) {
220        this.mesh.children[i].position.sub(this.avgPosition);
221      }
222    }
223  }
224}
225
226export default Framstick;
Note: See TracBrowser for help on using the repository browser.