openstudio-common-measures 0.10.0 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (212) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test_with_openstudio.yml +1 -1
  3. data/CHANGELOG.md +13 -0
  4. data/LICENSE.md +1 -1
  5. data/README.md +1 -0
  6. data/doc_templates/LICENSE.md +1 -1
  7. data/lib/measures/AddCostPerAreaToConstruction/LICENSE.md +1 -1
  8. data/lib/measures/AddCostPerAreaToConstruction/measure.xml +3 -3
  9. data/lib/measures/AddCostPerFloorAreaToBuilding/LICENSE.md +1 -1
  10. data/lib/measures/AddCostPerFloorAreaToBuilding/measure.xml +3 -3
  11. data/lib/measures/AddCostPerFloorAreaToElectricEquipment/LICENSE.md +1 -1
  12. data/lib/measures/AddCostPerFloorAreaToElectricEquipment/measure.xml +3 -3
  13. data/lib/measures/AddCostPerFloorAreaToLights/LICENSE.md +1 -1
  14. data/lib/measures/AddCostPerFloorAreaToLights/measure.xml +3 -3
  15. data/lib/measures/AddCostPerFloorAreaUnusedToLights/LICENSE.md +1 -1
  16. data/lib/measures/AddCostPerFloorAreaUnusedToLights/measure.xml +3 -3
  17. data/lib/measures/AddCostToSupplySideHVACComponentByAirLoop/LICENSE.md +1 -1
  18. data/lib/measures/AddCostToSupplySideHVACComponentByAirLoop/measure.xml +4 -4
  19. data/lib/measures/AddCostperAreatoUnusedConstruction/LICENSE.md +1 -1
  20. data/lib/measures/AddCostperAreatoUnusedConstruction/measure.xml +3 -3
  21. data/lib/measures/AddExteriorLights/LICENSE.md +1 -1
  22. data/lib/measures/AddExteriorLights/measure.xml +3 -3
  23. data/lib/measures/AddMeter/LICENSE.md +1 -1
  24. data/lib/measures/AddMeter/measure.xml +3 -3
  25. data/lib/measures/AddOutputDiagnostics/LICENSE.md +1 -1
  26. data/lib/measures/AddOutputDiagnostics/measure.rb +1 -1
  27. data/lib/measures/AddOutputDiagnostics/measure.xml +5 -5
  28. data/lib/measures/AddOutputVariable/LICENSE.md +1 -1
  29. data/lib/measures/AddOutputVariable/measure.xml +3 -3
  30. data/lib/measures/AddSimplePvToShadingSurfacesByType/LICENSE.md +1 -1
  31. data/lib/measures/AddSimplePvToShadingSurfacesByType/measure.xml +3 -3
  32. data/lib/measures/AddThermalComfortModelTypes/LICENSE.md +1 -1
  33. data/lib/measures/AddThermalComfortModelTypes/measure.xml +3 -3
  34. data/lib/measures/AdjustSystemEfficiencies/LICENSE.md +1 -1
  35. data/lib/measures/AdjustSystemEfficiencies/measure.xml +3 -3
  36. data/lib/measures/AdjustThermostatSetpointsByDegrees/LICENSE.md +1 -1
  37. data/lib/measures/AdjustThermostatSetpointsByDegrees/measure.xml +3 -3
  38. data/lib/measures/ChangeBuildingLocation/LICENSE.md +1 -1
  39. data/lib/measures/ChangeBuildingLocation/measure.xml +23 -5
  40. data/lib/measures/ChangeBuildingLocation/resources/epw.rb +7 -2
  41. data/lib/measures/EnableIdealAirLoadsForAllZones/LICENSE.md +1 -1
  42. data/lib/measures/EnableIdealAirLoadsForAllZones/measure.xml +3 -3
  43. data/lib/measures/ExportScheduleCSV/LICENSE.md +1 -1
  44. data/lib/measures/ExportScheduleCSV/measure.xml +3 -3
  45. data/lib/measures/ImportEnvelopeAndInternalLoadsFromIdf/LICENSE.md +1 -1
  46. data/lib/measures/ImportEnvelopeAndInternalLoadsFromIdf/measure.xml +3 -3
  47. data/lib/measures/MeterFlodPlot/LICENSE.md +1 -1
  48. data/lib/measures/MeterFlodPlot/measure.xml +3 -3
  49. data/lib/measures/ModifyEnergyPlusCoilCoolingDXSingleSpeedObjects/LICENSE.md +1 -1
  50. data/lib/measures/ModifyEnergyPlusCoilCoolingDXSingleSpeedObjects/measure.xml +3 -3
  51. data/lib/measures/ModifyEnergyPlusFanVariableVolumeObjects/LICENSE.md +1 -1
  52. data/lib/measures/ModifyEnergyPlusFanVariableVolumeObjects/measure.xml +3 -3
  53. data/lib/measures/PredictedMeanVote/LICENSE.md +1 -1
  54. data/lib/measures/PredictedMeanVote/measure.xml +3 -3
  55. data/lib/measures/RemoveInternalLoadsDirectlyAssignedToSpaces/LICENSE.md +1 -1
  56. data/lib/measures/RemoveInternalLoadsDirectlyAssignedToSpaces/measure.xml +3 -3
  57. data/lib/measures/RemoveUnusedDefaultProfiles/LICENSE.md +1 -1
  58. data/lib/measures/RemoveUnusedDefaultProfiles/measure.xml +3 -3
  59. data/lib/measures/ReplaceExteriorWindowConstruction/LICENSE.md +1 -1
  60. data/lib/measures/ReplaceExteriorWindowConstruction/measure.xml +3 -3
  61. data/lib/measures/ReplaceModel/LICENSE.md +1 -1
  62. data/lib/measures/ReplaceModel/measure.xml +3 -3
  63. data/lib/measures/ReplaceThermostatSchedules/LICENSE.md +1 -1
  64. data/lib/measures/ReplaceThermostatSchedules/measure.xml +5 -5
  65. data/lib/measures/ReportModelChanges/LICENSE.md +1 -1
  66. data/lib/measures/ReportModelChanges/measure.xml +3 -3
  67. data/lib/measures/RunPeriod/LICENSE.md +1 -1
  68. data/lib/measures/RunPeriod/measure.xml +3 -3
  69. data/lib/measures/RunPeriodMultiple/LICENSE.md +1 -1
  70. data/lib/measures/RunPeriodMultiple/measure.xml +3 -3
  71. data/lib/measures/ServerDirectoryCleanup/LICENSE.md +1 -1
  72. data/lib/measures/ServerDirectoryCleanup/README.md +14 -14
  73. data/lib/measures/ServerDirectoryCleanup/measure.rb +22 -18
  74. data/lib/measures/ServerDirectoryCleanup/measure.xml +25 -25
  75. data/lib/measures/SetCOPforSingleSpeedDXCoolingUnits/LICENSE.md +1 -1
  76. data/lib/measures/SetCOPforSingleSpeedDXCoolingUnits/measure.xml +5 -5
  77. data/lib/measures/SetCOPforTwoSpeedDXCoolingUnits/LICENSE.md +1 -1
  78. data/lib/measures/SetCOPforTwoSpeedDXCoolingUnits/measure.xml +5 -5
  79. data/lib/measures/SetEnergyPlusInfiltrationFlowRatePerFloorArea/LICENSE.md +1 -1
  80. data/lib/measures/SetEnergyPlusInfiltrationFlowRatePerFloorArea/measure.xml +3 -3
  81. data/lib/measures/SetEnergyPlusLightObjectsLPD/LICENSE.md +1 -1
  82. data/lib/measures/SetEnergyPlusLightObjectsLPD/measure.xml +3 -3
  83. data/lib/measures/SetEnergyPlusMinimumOutdoorAirFlowRate/LICENSE.md +1 -1
  84. data/lib/measures/SetEnergyPlusMinimumOutdoorAirFlowRate/measure.xml +3 -3
  85. data/lib/measures/SetGasBurnerEfficiency/LICENSE.md +1 -1
  86. data/lib/measures/SetGasBurnerEfficiency/measure.xml +5 -5
  87. data/lib/measures/SetLifecycleCostParameters/LICENSE.md +1 -1
  88. data/lib/measures/SetLifecycleCostParameters/measure.xml +3 -3
  89. data/lib/measures/SetLightingLoadsByLPD/LICENSE.md +1 -1
  90. data/lib/measures/SetLightingLoadsByLPD/measure.xml +5 -5
  91. data/lib/measures/SetSpaceInfiltrationByExteriorSurfaceArea/LICENSE.md +1 -1
  92. data/lib/measures/SetSpaceInfiltrationByExteriorSurfaceArea/measure.xml +3 -3
  93. data/lib/measures/SetThermostatSchedules/LICENSE.md +1 -1
  94. data/lib/measures/SetThermostatSchedules/measure.xml +5 -5
  95. data/lib/measures/ShiftScheduleProfileTime/LICENSE.md +1 -1
  96. data/lib/measures/ShiftScheduleProfileTime/measure.xml +5 -5
  97. data/lib/measures/SwapLightsDefinition/LICENSE.md +1 -1
  98. data/lib/measures/SwapLightsDefinition/measure.xml +3 -3
  99. data/lib/measures/UnmetLoadHoursTroubleshooting/LICENSE.md +1 -1
  100. data/lib/measures/UnmetLoadHoursTroubleshooting/measure.xml +3 -3
  101. data/lib/measures/VentilationQAQC/LICENSE.md +1 -1
  102. data/lib/measures/VentilationQAQC/measure.xml +3 -3
  103. data/lib/measures/XcelEDAReportingandQAQC/LICENSE.md +1 -1
  104. data/lib/measures/XcelEDAReportingandQAQC/measure.xml +3 -3
  105. data/lib/measures/XcelEDATariffSelectionandModelSetup/LICENSE.md +1 -1
  106. data/lib/measures/XcelEDATariffSelectionandModelSetup/measure.xml +3 -3
  107. data/lib/measures/ZoneReport/LICENSE.md +1 -1
  108. data/lib/measures/ZoneReport/measure.xml +3 -3
  109. data/lib/measures/add_ems_emissions_reporting/LICENSE.md +1 -1
  110. data/lib/measures/add_ems_emissions_reporting/measure.xml +3 -3
  111. data/lib/measures/add_ems_to_control_ev_charging/LICENSE.md +1 -1
  112. data/lib/measures/add_ems_to_control_ev_charging/measure.xml +3 -3
  113. data/lib/measures/add_ev_load/LICENSE.md +1 -1
  114. data/lib/measures/add_ev_load/measure.xml +3 -3
  115. data/lib/measures/add_rooftop_pv/LICENSE.md +1 -1
  116. data/lib/measures/add_rooftop_pv/measure.xml +3 -3
  117. data/lib/measures/add_zone_mixing_object/LICENSE.md +1 -1
  118. data/lib/measures/add_zone_mixing_object/measure.xml +3 -3
  119. data/lib/measures/add_zone_ventilation_design_flow_rate_object/LICENSE.md +1 -1
  120. data/lib/measures/add_zone_ventilation_design_flow_rate_object/measure.xml +3 -3
  121. data/lib/measures/air_wall_zone_mixing/LICENSE.md +1 -1
  122. data/lib/measures/air_wall_zone_mixing/measure.xml +3 -3
  123. data/lib/measures/create_csv_output/LICENSE.md +1 -1
  124. data/lib/measures/create_csv_output/measure.xml +3 -3
  125. data/lib/measures/envelope_and_internal_load_breakdown/LICENSE.md +1 -1
  126. data/lib/measures/envelope_and_internal_load_breakdown/measure.xml +3 -3
  127. data/lib/measures/example_report/LICENSE.md +1 -1
  128. data/lib/measures/example_report/measure.xml +3 -3
  129. data/lib/measures/gem_env_report/LICENSE.md +1 -1
  130. data/lib/measures/gem_env_report/measure.xml +3 -3
  131. data/lib/measures/generic_qaqc/LICENSE.md +1 -1
  132. data/lib/measures/generic_qaqc/README.md +0 -32
  133. data/lib/measures/generic_qaqc/measure.rb +5 -2
  134. data/lib/measures/generic_qaqc/measure.xml +5 -61
  135. data/lib/measures/get_site_from_building_component_library/LICENSE.md +1 -1
  136. data/lib/measures/get_site_from_building_component_library/measure.xml +3 -3
  137. data/lib/measures/hvac_psychrometric_chart/LICENSE.md +1 -1
  138. data/lib/measures/hvac_psychrometric_chart/measure.xml +3 -3
  139. data/lib/measures/inject_idf_objects/LICENSE.md +1 -1
  140. data/lib/measures/inject_idf_objects/measure.xml +3 -3
  141. data/lib/measures/openstudio_results/LICENSE.md +1 -1
  142. data/lib/measures/openstudio_results/README.md +10 -2
  143. data/lib/measures/openstudio_results/measure.rb +19 -7
  144. data/lib/measures/openstudio_results/measure.xml +80 -21
  145. data/lib/measures/openstudio_results/resources/Siz.AirConditionerVariableRefrigerantFlow.rb +1 -1
  146. data/lib/measures/openstudio_results/resources/Siz.CoilCoolingDXMultiSpeed.rb +10 -0
  147. data/lib/measures/openstudio_results/resources/Siz.CoilCoolingDXMultiSpeedStageData.rb +3 -1
  148. data/lib/measures/openstudio_results/resources/Siz.CoilCoolingDXSingleSpeed.rb +2 -2
  149. data/lib/measures/openstudio_results/resources/Siz.CoilCoolingDXTwoSpeed.rb +4 -3
  150. data/lib/measures/openstudio_results/resources/Siz.CoilCoolingWaterToAirHeatPumpEquationFit.rb +6 -0
  151. data/lib/measures/openstudio_results/resources/Siz.CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit.rb +10 -0
  152. data/lib/measures/openstudio_results/resources/Siz.CoilHeatingDXMultiSpeed.rb +10 -0
  153. data/lib/measures/openstudio_results/resources/Siz.CoilHeatingDXSingleSpeed.rb +1 -1
  154. data/lib/measures/openstudio_results/resources/Siz.CoilHeatingWaterToAirHeatPumpEquationFit.rb +6 -0
  155. data/lib/measures/openstudio_results/resources/Siz.CoilHeatingWaterToAirHeatPumpVariableSpeedEquationFit.rb +10 -0
  156. data/lib/measures/openstudio_results/resources/Siz.CoilPerformanceDXCooling.rb +1 -1
  157. data/lib/measures/openstudio_results/resources/Siz.FanSystemModel.rb +31 -0
  158. data/lib/measures/openstudio_results/resources/Siz.Model.rb +1 -0
  159. data/lib/measures/openstudio_results/resources/bootstrap.min.css +5 -0
  160. data/lib/measures/openstudio_results/resources/bootstrap.min.js +6 -0
  161. data/lib/measures/openstudio_results/resources/d3.min.js +5 -0
  162. data/lib/measures/openstudio_results/resources/dimple.v2.1.2.min.js +3 -0
  163. data/lib/measures/openstudio_results/resources/jquery.min.js +6 -0
  164. data/lib/measures/openstudio_results/resources/os_lib_reporting.rb +12 -0
  165. data/lib/measures/openstudio_results/resources/report.html.erb +5 -5
  166. data/lib/measures/remove_orphan_objects_and_unused_resources/LICENSE.md +1 -1
  167. data/lib/measures/remove_orphan_objects_and_unused_resources/measure.xml +3 -3
  168. data/lib/measures/set_electric_equipment_loads_by_epd/LICENSE.md +1 -1
  169. data/lib/measures/set_electric_equipment_loads_by_epd/measure.xml +5 -5
  170. data/lib/measures/set_exterior_walls_and_floors_to_adiabatic/LICENSE.md +1 -1
  171. data/lib/measures/set_exterior_walls_and_floors_to_adiabatic/measure.xml +3 -3
  172. data/lib/measures/set_run_period/LICENSE.md +1 -1
  173. data/lib/measures/set_run_period/measure.xml +3 -3
  174. data/lib/measures/set_space_infiltration_per_exterior_area/LICENSE.md +1 -1
  175. data/lib/measures/set_space_infiltration_per_exterior_area/README.md +11 -0
  176. data/lib/measures/set_space_infiltration_per_exterior_area/measure.rb +13 -0
  177. data/lib/measures/set_space_infiltration_per_exterior_area/measure.xml +24 -5
  178. data/lib/measures/shadow_calculation/LICENSE.md +1 -1
  179. data/lib/measures/shadow_calculation/measure.xml +3 -3
  180. data/lib/measures/simulation_control/README.md +120 -0
  181. data/lib/measures/simulation_control/README.md.erb +42 -0
  182. data/lib/measures/simulation_control/measure.rb +169 -0
  183. data/lib/measures/simulation_control/measure.xml +246 -0
  184. data/lib/measures/tariff_selection_block/LICENSE.md +1 -1
  185. data/lib/measures/tariff_selection_block/measure.xml +3 -3
  186. data/lib/measures/tariff_selection_flat/LICENSE.md +1 -1
  187. data/lib/measures/tariff_selection_flat/measure.xml +3 -3
  188. data/lib/measures/tariff_selection_generic/LICENSE.md +1 -1
  189. data/lib/measures/tariff_selection_generic/measure.xml +3 -3
  190. data/lib/measures/tariff_selection_time_and_date_dependant/LICENSE.md +1 -1
  191. data/lib/measures/tariff_selection_time_and_date_dependant/measure.xml +3 -3
  192. data/lib/measures/view_data/LICENSE.md +1 -1
  193. data/lib/measures/view_data/README.md +8 -0
  194. data/lib/measures/view_data/measure.rb +32 -7
  195. data/lib/measures/view_data/measure.xml +50 -7
  196. data/lib/measures/view_data/resources/js/TweenLite.2.1.3.min.js +12 -0
  197. data/lib/measures/view_data/resources/js/dat.gui.0.7.9.min.js +13 -0
  198. data/lib/measures/view_data/resources/js/three.orbitcontrols.js +706 -0
  199. data/lib/measures/view_data/resources/js/three.r98.min.js +964 -0
  200. data/lib/measures/view_data/resources/report.html.in +170 -1837
  201. data/lib/measures/view_model/LICENSE.md +1 -1
  202. data/lib/measures/view_model/README.md +7 -1
  203. data/lib/measures/view_model/measure.rb +28 -2
  204. data/lib/measures/view_model/measure.xml +52 -8
  205. data/lib/measures/view_model/resources/js/TweenLite.2.1.3.min.js +12 -0
  206. data/lib/measures/view_model/resources/js/dat.gui.0.7.9.min.js +13 -0
  207. data/lib/measures/view_model/resources/js/three.orbitcontrols.js +706 -0
  208. data/lib/measures/view_model/resources/js/three.r98.min.js +964 -0
  209. data/lib/measures/view_model/resources/report.html.in +168 -1835
  210. data/lib/openstudio/common_measures/version.rb +1 -1
  211. data/openstudio-common-measures.gemspec +2 -3
  212. metadata +25 -21
@@ -0,0 +1,706 @@
1
+ /**
2
+ * @author qiao / https://github.com/qiao
3
+ * @author mrdoob / http://mrdoob.com
4
+ * @author alteredq / http://alteredqualia.com/
5
+ * @author WestLangley / http://github.com/WestLangley
6
+ * @author erich666 / http://erichaines.com
7
+ */
8
+ /*global THREE, console */
9
+
10
+ // This set of controls performs orbiting, dollying (zooming), and panning. It maintains
11
+ // the "up" direction as +Y, unlike the TrackballControls. Touch on tablet and phones is
12
+ // supported.
13
+ //
14
+ // Orbit - left mouse / touch: one finger move
15
+ // Zoom - middle mouse, or mousewheel / touch: two finger spread or squish
16
+ // Pan - right mouse, or arrow keys / touch: three finter swipe
17
+
18
+ THREE.OrbitControls = function ( object, domElement ) {
19
+
20
+ this.object = object;
21
+ this.domElement = ( domElement !== undefined ) ? domElement : document;
22
+
23
+ // API
24
+
25
+ // Set to false to disable this control
26
+ this.enabled = true;
27
+
28
+ // "target" sets the location of focus, where the control orbits around
29
+ // and where it pans with respect to.
30
+ this.target = new THREE.Vector3();
31
+
32
+ // center is old, deprecated; use "target" instead
33
+ this.center = this.target;
34
+
35
+ // This option actually enables dollying in and out; left as "zoom" for
36
+ // backwards compatibility
37
+ this.noZoom = false;
38
+ this.zoomSpeed = 1.0;
39
+
40
+ // Limits to how far you can dolly in and out ( PerspectiveCamera only )
41
+ this.minDistance = 0;
42
+ this.maxDistance = Infinity;
43
+
44
+ // Limits to how far you can zoom in and out ( OrthographicCamera only )
45
+ this.minZoom = 0;
46
+ this.maxZoom = Infinity;
47
+
48
+ // Set to true to disable this control
49
+ this.noRotate = false;
50
+ this.rotateSpeed = 1.0;
51
+
52
+ // Set to true to disable this control
53
+ this.noPan = false;
54
+ this.keyPanSpeed = 7.0; // pixels moved per arrow key push
55
+
56
+ // Set to true to automatically rotate around the target
57
+ this.autoRotate = false;
58
+ this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60
59
+
60
+ // How far you can orbit vertically, upper and lower limits.
61
+ // Range is 0 to Math.PI radians.
62
+ this.minPolarAngle = 0; // radians
63
+ this.maxPolarAngle = Math.PI; // radians
64
+
65
+ // How far you can orbit horizontally, upper and lower limits.
66
+ // If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ].
67
+ this.minAzimuthAngle = - Infinity; // radians
68
+ this.maxAzimuthAngle = Infinity; // radians
69
+
70
+ // Set to true to disable use of the keys
71
+ this.noKeys = false;
72
+
73
+ // The four arrow keys
74
+ this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 };
75
+
76
+ // Mouse buttons
77
+ this.mouseButtons = { ORBIT: THREE.MOUSE.LEFT, ZOOM: THREE.MOUSE.MIDDLE, PAN: THREE.MOUSE.RIGHT };
78
+
79
+ ////////////
80
+ // internals
81
+
82
+ var scope = this;
83
+
84
+ var EPS = 0.000001;
85
+
86
+ var rotateStart = new THREE.Vector2();
87
+ var rotateEnd = new THREE.Vector2();
88
+ var rotateDelta = new THREE.Vector2();
89
+
90
+ var panStart = new THREE.Vector2();
91
+ var panEnd = new THREE.Vector2();
92
+ var panDelta = new THREE.Vector2();
93
+ var panOffset = new THREE.Vector3();
94
+
95
+ var offset = new THREE.Vector3();
96
+
97
+ var dollyStart = new THREE.Vector2();
98
+ var dollyEnd = new THREE.Vector2();
99
+ var dollyDelta = new THREE.Vector2();
100
+
101
+ var theta;
102
+ var phi;
103
+ var phiDelta = 0;
104
+ var thetaDelta = 0;
105
+ var scale = 1;
106
+ var pan = new THREE.Vector3();
107
+
108
+ var lastPosition = new THREE.Vector3();
109
+ var lastQuaternion = new THREE.Quaternion();
110
+
111
+ var STATE = { NONE : -1, ROTATE : 0, DOLLY : 1, PAN : 2, TOUCH_ROTATE : 3, TOUCH_DOLLY : 4, TOUCH_PAN : 5 };
112
+
113
+ var state = STATE.NONE;
114
+
115
+ // for reset
116
+
117
+ this.target0 = this.target.clone();
118
+ this.position0 = this.object.position.clone();
119
+ this.zoom0 = this.object.zoom;
120
+
121
+ // so camera.up is the orbit axis
122
+
123
+ var quat = new THREE.Quaternion().setFromUnitVectors( object.up, new THREE.Vector3( 0, 1, 0 ) );
124
+ var quatInverse = quat.clone().inverse();
125
+
126
+ // events
127
+
128
+ var changeEvent = { type: 'change' };
129
+ var startEvent = { type: 'start' };
130
+ var endEvent = { type: 'end' };
131
+
132
+ this.rotateLeft = function ( angle ) {
133
+
134
+ if ( angle === undefined ) {
135
+
136
+ angle = getAutoRotationAngle();
137
+
138
+ }
139
+
140
+ thetaDelta -= angle;
141
+
142
+ };
143
+
144
+ this.rotateUp = function ( angle ) {
145
+
146
+ if ( angle === undefined ) {
147
+
148
+ angle = getAutoRotationAngle();
149
+
150
+ }
151
+
152
+ phiDelta -= angle;
153
+
154
+ };
155
+
156
+ // pass in distance in world space to move left
157
+ this.panLeft = function ( distance ) {
158
+
159
+ var te = this.object.matrix.elements;
160
+
161
+ // get X column of matrix
162
+ panOffset.set( te[ 0 ], te[ 1 ], te[ 2 ] );
163
+ panOffset.multiplyScalar( - distance );
164
+
165
+ pan.add( panOffset );
166
+
167
+ };
168
+
169
+ // pass in distance in world space to move up
170
+ this.panUp = function ( distance ) {
171
+
172
+ var te = this.object.matrix.elements;
173
+
174
+ // get Y column of matrix
175
+ panOffset.set( te[ 4 ], te[ 5 ], te[ 6 ] );
176
+ panOffset.multiplyScalar( distance );
177
+
178
+ pan.add( panOffset );
179
+
180
+ };
181
+
182
+ // pass in x,y of change desired in pixel space,
183
+ // right and down are positive
184
+ this.pan = function ( deltaX, deltaY ) {
185
+
186
+ var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
187
+
188
+ if ( scope.object instanceof THREE.PerspectiveCamera ) {
189
+
190
+ // perspective
191
+ var position = scope.object.position;
192
+ var offset = position.clone().sub( scope.target );
193
+ var targetDistance = offset.length();
194
+
195
+ // half of the fov is center to top of screen
196
+ targetDistance *= Math.tan( ( scope.object.fov / 2 ) * Math.PI / 180.0 );
197
+
198
+ // we actually don't use screenWidth, since perspective camera is fixed to screen height
199
+ scope.panLeft( 2 * deltaX * targetDistance / element.clientHeight );
200
+ scope.panUp( 2 * deltaY * targetDistance / element.clientHeight );
201
+
202
+ } else if ( scope.object instanceof THREE.OrthographicCamera ) {
203
+
204
+ // orthographic
205
+ scope.panLeft( deltaX * (scope.object.right - scope.object.left) / element.clientWidth );
206
+ scope.panUp( deltaY * (scope.object.top - scope.object.bottom) / element.clientHeight );
207
+
208
+ } else {
209
+
210
+ // camera neither orthographic or perspective
211
+ console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' );
212
+
213
+ }
214
+
215
+ };
216
+
217
+ this.dollyIn = function ( dollyScale ) {
218
+
219
+ if ( dollyScale === undefined ) {
220
+
221
+ dollyScale = getZoomScale();
222
+
223
+ }
224
+
225
+ if ( scope.object instanceof THREE.PerspectiveCamera ) {
226
+
227
+ scale /= dollyScale;
228
+
229
+ } else if ( scope.object instanceof THREE.OrthographicCamera ) {
230
+
231
+ scope.object.zoom = Math.max( this.minZoom, Math.min( this.maxZoom, this.object.zoom * dollyScale ) );
232
+ scope.object.updateProjectionMatrix();
233
+ scope.dispatchEvent( changeEvent );
234
+
235
+ } else {
236
+
237
+ console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );
238
+
239
+ }
240
+
241
+ };
242
+
243
+ this.dollyOut = function ( dollyScale ) {
244
+
245
+ if ( dollyScale === undefined ) {
246
+
247
+ dollyScale = getZoomScale();
248
+
249
+ }
250
+
251
+ if ( scope.object instanceof THREE.PerspectiveCamera ) {
252
+
253
+ scale *= dollyScale;
254
+
255
+ } else if ( scope.object instanceof THREE.OrthographicCamera ) {
256
+
257
+ scope.object.zoom = Math.max( this.minZoom, Math.min( this.maxZoom, this.object.zoom / dollyScale ) );
258
+ scope.object.updateProjectionMatrix();
259
+ scope.dispatchEvent( changeEvent );
260
+
261
+ } else {
262
+
263
+ console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );
264
+
265
+ }
266
+
267
+ };
268
+
269
+ this.update = function () {
270
+
271
+ var position = this.object.position;
272
+
273
+ offset.copy( position ).sub( this.target );
274
+
275
+ // rotate offset to "y-axis-is-up" space
276
+ offset.applyQuaternion( quat );
277
+
278
+ // angle from z-axis around y-axis
279
+
280
+ theta = Math.atan2( offset.x, offset.z );
281
+
282
+ // angle from y-axis
283
+
284
+ phi = Math.atan2( Math.sqrt( offset.x * offset.x + offset.z * offset.z ), offset.y );
285
+
286
+ if ( this.autoRotate && state === STATE.NONE ) {
287
+
288
+ this.rotateLeft( getAutoRotationAngle() );
289
+
290
+ }
291
+
292
+ theta += thetaDelta;
293
+ phi += phiDelta;
294
+
295
+ // restrict theta to be between desired limits
296
+ theta = Math.max( this.minAzimuthAngle, Math.min( this.maxAzimuthAngle, theta ) );
297
+
298
+ // restrict phi to be between desired limits
299
+ phi = Math.max( this.minPolarAngle, Math.min( this.maxPolarAngle, phi ) );
300
+
301
+ // restrict phi to be betwee EPS and PI-EPS
302
+ phi = Math.max( EPS, Math.min( Math.PI - EPS, phi ) );
303
+
304
+ var radius = offset.length() * scale;
305
+
306
+ // restrict radius to be between desired limits
307
+ radius = Math.max( this.minDistance, Math.min( this.maxDistance, radius ) );
308
+
309
+ // move target to panned location
310
+ this.target.add( pan );
311
+
312
+ offset.x = radius * Math.sin( phi ) * Math.sin( theta );
313
+ offset.y = radius * Math.cos( phi );
314
+ offset.z = radius * Math.sin( phi ) * Math.cos( theta );
315
+
316
+ // rotate offset back to "camera-up-vector-is-up" space
317
+ offset.applyQuaternion( quatInverse );
318
+
319
+ position.copy( this.target ).add( offset );
320
+
321
+ this.object.lookAt( this.target );
322
+
323
+ thetaDelta = 0;
324
+ phiDelta = 0;
325
+ scale = 1;
326
+ pan.set( 0, 0, 0 );
327
+
328
+ // update condition is:
329
+ // min(camera displacement, camera rotation in radians)^2 > EPS
330
+ // using small-angle approximation cos(x/2) = 1 - x^2 / 8
331
+
332
+ if ( lastPosition.distanceToSquared( this.object.position ) > EPS
333
+ || 8 * (1 - lastQuaternion.dot(this.object.quaternion)) > EPS ) {
334
+
335
+ this.dispatchEvent( changeEvent );
336
+
337
+ lastPosition.copy( this.object.position );
338
+ lastQuaternion.copy (this.object.quaternion );
339
+
340
+ }
341
+
342
+ };
343
+
344
+
345
+ this.reset = function () {
346
+
347
+ state = STATE.NONE;
348
+
349
+ this.target.copy( this.target0 );
350
+ this.object.position.copy( this.position0 );
351
+ this.object.zoom = this.zoom0;
352
+
353
+ this.object.updateProjectionMatrix();
354
+ this.dispatchEvent( changeEvent );
355
+
356
+ this.update();
357
+
358
+ };
359
+
360
+ this.getPolarAngle = function () {
361
+
362
+ return phi;
363
+
364
+ };
365
+
366
+ this.getAzimuthalAngle = function () {
367
+
368
+ return theta
369
+
370
+ };
371
+
372
+ function getAutoRotationAngle() {
373
+
374
+ return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
375
+
376
+ }
377
+
378
+ function getZoomScale() {
379
+
380
+ return Math.pow( 0.95, scope.zoomSpeed );
381
+
382
+ }
383
+
384
+ function onMouseDown( event ) {
385
+
386
+ if ( scope.enabled === false ) return;
387
+ event.preventDefault();
388
+
389
+ if ( event.button === scope.mouseButtons.ORBIT ) {
390
+ if ( scope.noRotate === true ) return;
391
+
392
+ state = STATE.ROTATE;
393
+
394
+ rotateStart.set( event.clientX, event.clientY );
395
+
396
+ } else if ( event.button === scope.mouseButtons.ZOOM ) {
397
+ if ( scope.noZoom === true ) return;
398
+
399
+ state = STATE.DOLLY;
400
+
401
+ dollyStart.set( event.clientX, event.clientY );
402
+
403
+ } else if ( event.button === scope.mouseButtons.PAN ) {
404
+ if ( scope.noPan === true ) return;
405
+
406
+ state = STATE.PAN;
407
+
408
+ panStart.set( event.clientX, event.clientY );
409
+
410
+ }
411
+
412
+ if ( state !== STATE.NONE ) {
413
+ document.addEventListener( 'mousemove', onMouseMove, false );
414
+ document.addEventListener( 'mouseup', onMouseUp, false );
415
+ scope.dispatchEvent( startEvent );
416
+ }
417
+
418
+ }
419
+
420
+ function onMouseMove( event ) {
421
+
422
+ if ( scope.enabled === false ) return;
423
+
424
+ event.preventDefault();
425
+
426
+ var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
427
+
428
+ if ( state === STATE.ROTATE ) {
429
+
430
+ if ( scope.noRotate === true ) return;
431
+
432
+ rotateEnd.set( event.clientX, event.clientY );
433
+ rotateDelta.subVectors( rotateEnd, rotateStart );
434
+
435
+ // rotating across whole screen goes 360 degrees around
436
+ scope.rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed );
437
+
438
+ // rotating up and down along whole screen attempts to go 360, but limited to 180
439
+ scope.rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed );
440
+
441
+ rotateStart.copy( rotateEnd );
442
+
443
+ } else if ( state === STATE.DOLLY ) {
444
+
445
+ if ( scope.noZoom === true ) return;
446
+
447
+ dollyEnd.set( event.clientX, event.clientY );
448
+ dollyDelta.subVectors( dollyEnd, dollyStart );
449
+
450
+ if ( dollyDelta.y > 0 ) {
451
+
452
+ scope.dollyIn();
453
+
454
+ } else if ( dollyDelta.y < 0 ) {
455
+
456
+ scope.dollyOut();
457
+
458
+ }
459
+
460
+ dollyStart.copy( dollyEnd );
461
+
462
+ } else if ( state === STATE.PAN ) {
463
+
464
+ if ( scope.noPan === true ) return;
465
+
466
+ panEnd.set( event.clientX, event.clientY );
467
+ panDelta.subVectors( panEnd, panStart );
468
+
469
+ scope.pan( panDelta.x, panDelta.y );
470
+
471
+ panStart.copy( panEnd );
472
+
473
+ }
474
+
475
+ if ( state !== STATE.NONE ) scope.update();
476
+
477
+ }
478
+
479
+ function onMouseUp( /* event */ ) {
480
+
481
+ if ( scope.enabled === false ) return;
482
+
483
+ document.removeEventListener( 'mousemove', onMouseMove, false );
484
+ document.removeEventListener( 'mouseup', onMouseUp, false );
485
+ scope.dispatchEvent( endEvent );
486
+ state = STATE.NONE;
487
+
488
+ }
489
+
490
+ function onMouseWheel( event ) {
491
+
492
+ if ( scope.enabled === false || scope.noZoom === true || state !== STATE.NONE ) return;
493
+
494
+ event.preventDefault();
495
+ event.stopPropagation();
496
+
497
+ var delta = 0;
498
+
499
+ if ( event.wheelDelta !== undefined ) { // WebKit / Opera / Explorer 9
500
+
501
+ delta = event.wheelDelta;
502
+
503
+ } else if ( event.detail !== undefined ) { // Firefox
504
+
505
+ delta = - event.detail;
506
+
507
+ }
508
+
509
+ if ( delta > 0 ) {
510
+
511
+ scope.dollyOut();
512
+
513
+ } else if ( delta < 0 ) {
514
+
515
+ scope.dollyIn();
516
+
517
+ }
518
+
519
+ scope.update();
520
+ scope.dispatchEvent( startEvent );
521
+ scope.dispatchEvent( endEvent );
522
+
523
+ }
524
+
525
+ function onKeyDown( event ) {
526
+
527
+ if ( scope.enabled === false || scope.noKeys === true || scope.noPan === true ) return;
528
+
529
+ switch ( event.keyCode ) {
530
+
531
+ case scope.keys.UP:
532
+ scope.pan( 0, scope.keyPanSpeed );
533
+ scope.update();
534
+ break;
535
+
536
+ case scope.keys.BOTTOM:
537
+ scope.pan( 0, - scope.keyPanSpeed );
538
+ scope.update();
539
+ break;
540
+
541
+ case scope.keys.LEFT:
542
+ scope.pan( scope.keyPanSpeed, 0 );
543
+ scope.update();
544
+ break;
545
+
546
+ case scope.keys.RIGHT:
547
+ scope.pan( - scope.keyPanSpeed, 0 );
548
+ scope.update();
549
+ break;
550
+
551
+ }
552
+
553
+ }
554
+
555
+ function touchstart( event ) {
556
+
557
+ if ( scope.enabled === false ) return;
558
+
559
+ switch ( event.touches.length ) {
560
+
561
+ case 1: // one-fingered touch: rotate
562
+
563
+ if ( scope.noRotate === true ) return;
564
+
565
+ state = STATE.TOUCH_ROTATE;
566
+
567
+ rotateStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
568
+ break;
569
+
570
+ case 2: // two-fingered touch: dolly
571
+
572
+ if ( scope.noZoom === true ) return;
573
+
574
+ state = STATE.TOUCH_DOLLY;
575
+
576
+ var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
577
+ var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
578
+ var distance = Math.sqrt( dx * dx + dy * dy );
579
+ dollyStart.set( 0, distance );
580
+ break;
581
+
582
+ case 3: // three-fingered touch: pan
583
+
584
+ if ( scope.noPan === true ) return;
585
+
586
+ state = STATE.TOUCH_PAN;
587
+
588
+ panStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
589
+ break;
590
+
591
+ default:
592
+
593
+ state = STATE.NONE;
594
+
595
+ }
596
+
597
+ if ( state !== STATE.NONE ) scope.dispatchEvent( startEvent );
598
+
599
+ }
600
+
601
+ function touchmove( event ) {
602
+
603
+ if ( scope.enabled === false ) return;
604
+
605
+ event.preventDefault();
606
+ event.stopPropagation();
607
+
608
+ var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
609
+
610
+ switch ( event.touches.length ) {
611
+
612
+ case 1: // one-fingered touch: rotate
613
+
614
+ if ( scope.noRotate === true ) return;
615
+ if ( state !== STATE.TOUCH_ROTATE ) return;
616
+
617
+ rotateEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
618
+ rotateDelta.subVectors( rotateEnd, rotateStart );
619
+
620
+ // rotating across whole screen goes 360 degrees around
621
+ scope.rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed );
622
+ // rotating up and down along whole screen attempts to go 360, but limited to 180
623
+ scope.rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed );
624
+
625
+ rotateStart.copy( rotateEnd );
626
+
627
+ scope.update();
628
+ break;
629
+
630
+ case 2: // two-fingered touch: dolly
631
+
632
+ if ( scope.noZoom === true ) return;
633
+ if ( state !== STATE.TOUCH_DOLLY ) return;
634
+
635
+ var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
636
+ var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
637
+ var distance = Math.sqrt( dx * dx + dy * dy );
638
+
639
+ dollyEnd.set( 0, distance );
640
+ dollyDelta.subVectors( dollyEnd, dollyStart );
641
+
642
+ if ( dollyDelta.y > 0 ) {
643
+
644
+ scope.dollyOut();
645
+
646
+ } else if ( dollyDelta.y < 0 ) {
647
+
648
+ scope.dollyIn();
649
+
650
+ }
651
+
652
+ dollyStart.copy( dollyEnd );
653
+
654
+ scope.update();
655
+ break;
656
+
657
+ case 3: // three-fingered touch: pan
658
+
659
+ if ( scope.noPan === true ) return;
660
+ if ( state !== STATE.TOUCH_PAN ) return;
661
+
662
+ panEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
663
+ panDelta.subVectors( panEnd, panStart );
664
+
665
+ scope.pan( panDelta.x, panDelta.y );
666
+
667
+ panStart.copy( panEnd );
668
+
669
+ scope.update();
670
+ break;
671
+
672
+ default:
673
+
674
+ state = STATE.NONE;
675
+
676
+ }
677
+
678
+ }
679
+
680
+ function touchend( /* event */ ) {
681
+
682
+ if ( scope.enabled === false ) return;
683
+
684
+ scope.dispatchEvent( endEvent );
685
+ state = STATE.NONE;
686
+
687
+ }
688
+
689
+ this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
690
+ this.domElement.addEventListener( 'mousedown', onMouseDown, false );
691
+ this.domElement.addEventListener( 'mousewheel', onMouseWheel, false );
692
+ this.domElement.addEventListener( 'DOMMouseScroll', onMouseWheel, false ); // firefox
693
+
694
+ this.domElement.addEventListener( 'touchstart', touchstart, false );
695
+ this.domElement.addEventListener( 'touchend', touchend, false );
696
+ this.domElement.addEventListener( 'touchmove', touchmove, false );
697
+
698
+ window.addEventListener( 'keydown', onKeyDown, false );
699
+
700
+ // force an update at start
701
+ this.update();
702
+
703
+ };
704
+
705
+ THREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype );
706
+ THREE.OrbitControls.prototype.constructor = THREE.OrbitControls;