API Docs for: 1.0.2
Show:

File: GIScene\Control\Measure.js

/**
 * The Measure-Control lets you pick two points of an Object by clicking. 
 * As a result you get the an Object containing the measured distance in scene units.
 * 
 * The measure-Event content looks like this:
 * 
 * 		{
 * 			distance: 			{Number in Scene units},
 * 			angleToNorth : 		{Number angle in degrees}
 * 		}
 * 
 * @namespace GIScene
 * @class Control.Measure
 * @constructor
 * @extends GIScene.Control
 * @param {THREE.Camera} camera
 * @param {Object} [config] Configuration properties. e.g. {color : new THREE.Color(0xff0000)}
 * 
 */

GIScene.Control.Measure = function(camera, config){
	//make this a control
	GIScene.Control.call(this);
	
	this.camera = camera;
	var defaults = {
		color: new THREE.Color( 0xff0000 )
	};
	/**
	 * The config which is used to initialize the Control. Merged from defaults and passed config Object.
	 * 
	 * @property config
	 * @type Object
	 */
	this.config = GIScene.Utils.mergeObjects(defaults, config || {}); 
	
	this.domElement = null; //will be set on activate
	this.measureables = [];	//must be set after objects/layers have been loaded
	var mouse = new THREE.Vector3(0,0,1);
	var projector = new THREE.Projector();
	var pickSymbol = null;
	var resultsLayer = null;
	var pickedPointMaterial = null;
	var measureLineMaterial = null;
	// var measureLineHiddenMaterial = null;
	// var foregroundScene = new THREE.Scene();
	
	// var onBeforeRender = function() {this.scene.renderer.clear();}.bind(this);
// 	
	// var onAfterRender = function() {
		// this.scene.renderer.clear( false, true, false );
		// this.scene.renderer.render( foregroundScene, this.camera );
	// }.bind(this);
	
	var onMouseDown = function(event) {
		var viewPortCoords = GIScene.Utils.getViewportCoordsFromDOMEvent(this.domElement,event);
		mouse.set(viewPortCoords.x, viewPortCoords.y, 1);
	}.bind(this);
	
	var onMouseUp = function(event){
		//get mouse ScreenCoords
		var viewPortCoords = GIScene.Utils.getViewportCoordsFromDOMEvent(this.domElement,event);
		
		//only set if down and up coords are the same
		if(mouse.equals(new THREE.Vector3().set(viewPortCoords.x, viewPortCoords.y, 1)) ){
			mouse.set(viewPortCoords.x, viewPortCoords.y, 1);
			var ray = projector.pickingRay(mouse, this.camera);
			var pickResults = ray.intersectObjects(this.measureables);
			var pickResult;
			for(var i=0; i < pickResults.length; i++){
				if(pickResults[i].object.geometry && pickResults[i].object.visible){
					pickResult = pickResults[i];
					break;
				};
			};
			if(pickResult){
				this.drawPickResult(pickResult);
			}
		}
	}.bind(this);
	
	/**
	 * Draws a cross symbol to where the user has picked and a connection line.
	 * 
	 * @method drawPickResult
	 * @param  {Object} pickResult A Raycaster intersect object 
	 */
	this.drawPickResult = function(pickResult) {
		
		if(resultsLayer.root.children.length<2){
			var pickedPointCoords = pickResult.point;
			//create point object
			pickedPointGeom = new THREE.Geometry();
			pickedPointGeom.vertices.push(pickedPointCoords);
		}
		
		if(resultsLayer.root.children.length==1){
			// set second point 
			var pickedPoint = new THREE.ParticleSystem(pickedPointGeom.clone(), pickedPointMaterial);
			resultsLayer.root.add(pickedPoint);
			
			//set measure Line
			var measureLineGeom = new THREE.Geometry();
			var measurePoint1 = resultsLayer.root.children[0].geometry.vertices[0];
			var measurePoint2 = resultsLayer.root.children[1].geometry.vertices[0];
			
			measureLineGeom.vertices.push(measurePoint1);
			measureLineGeom.vertices.push(measurePoint2);
			
			var measureLine = new THREE.Line(measureLineGeom, measureLineMaterial);
			resultsLayer.root.add(measureLine);
			
			// //draw in foreground
			// var measureLineHidden = new THREE.Line(measureLineGeom.clone(), measureLineHiddenMaterial);
			// foregroundScene.add(measureLineHidden);
			// this.scene.renderer.autoClear = false;
			// this.scene.addEventListener('beforeRender', onBeforeRender);
			// this.scene.addEventListener('afterRender', onAfterRender);
			
			//calc angle to v3 0,0,-1
			var north = new THREE.Vector3(0,0,-1);
			var mp2_2d = measurePoint2.clone().setY(0);
			var mp1_2d = measurePoint1.clone().setY(0);
			var measureDirection = mp2_2d.sub(mp1_2d);
			var isEastSide = (measureDirection.x >= 0)?true:false;
			var angle = north.angleTo(measureDirection);
			if(!isEastSide)angle = Math.PI*2 - angle;
			var angleDeg = THREE.Math.radToDeg(angle);
			
			var measureResult = {
				distance : measurePoint1.distanceTo(measurePoint2),
				angleToNorth : angleDeg
			};
			
			/**
			 * The measure event contains a content property with an result object
			 * 
			 * @event measure
			 */
			//pickResult has the following properties: distance, face, faceIndex, object, point
			this.dispatchEvent({type:'measure', content:measureResult});
		}
		
		if(resultsLayer.root.children.length==0){
			// set first point
			var pickedPoint = new THREE.ParticleSystem(pickedPointGeom.clone(), pickedPointMaterial);
			resultsLayer.root.add(pickedPoint);
		}
		
	};
	
	/**
	 * Activates this Control
	 * 
	 * @method activate
	 *  
	 */
	this.activate = function(){
		if(this.isActive) return;
		
		this.domElement = this.scene.canvas;
		resulstLayerConfig = {
			offset : this.scene.config.offset,
			layerGroup : "User-generated"
		};
		resultsLayer = new GIScene.Layer("Measurements", resulstLayerConfig);
		this.scene.addLayer(resultsLayer);
		pickSymbol = THREE.ImageUtils.loadTexture( GIScene.LIBRARYPATH + GIScene.RESOURCESPATH.replace(/([^\/])$/, "$1/") +"resources/images/particle_cross.png");
		pickedPointMaterial = new THREE.ParticleBasicMaterial({
												color:this.config.color,
												sizeAttenuation:false,
												size:32,
												map:pickSymbol,
												alphaTest:0.5	
											});
		measureLineMaterial = new THREE.LineBasicMaterial({
												color: this.config.color,
												linewidth:1
											});
		// measureLineHiddenMaterial = new THREE.LineBasicMaterial({
												// color: new THREE.Color(0xff0000),
												// linewidth:1
											// });
											
		
		//eventListeners
		this.domElement.addEventListener('mousedown',onMouseDown, false);
		this.domElement.addEventListener('mouseup',onMouseUp, false);
		
		//call super class method
		GIScene.Control.prototype.activate.call(this);
	};
	
	/**
	 * Deactivates this Control
	 * 
	 * @method deactivate
	 *  
	 */
	this.deactivate = function(){
		if(!this.isActive) return;
		
		this.domElement.removeEventListener('mousedown',onMouseDown, false);
		this.domElement.removeEventListener('mouseup',onMouseUp, false);
		this.scene.disposeLayer(resultsLayer);
		
		//call super class method
		GIScene.Control.prototype.deactivate.call(this);
	};
	
};

//Inherit from GIScene.Control
GIScene.Control.Measure.prototype = Object.create( GIScene.Control.prototype );