<%@ language="javascript"%>
<% /*
     $Revision$
     $Id$

    File:               3Dize.asp
    Description:
    Parameters:         allerlei custom parameters
    Context:            Vanuit ge
    Note:               De tekening staat in een andere directory (S("flexfilespath") + "/cad/vlucht/") maar moet dezelfde bestandsnaam hebben
                        als de gewone FG plattegrondtekening.
*/
 %>
<!--#include file="../Shared/common.inc" -->
<!--#include file="../slnkdwf/Slnk2IMG.inc" -->
<%
  FCLTHeader.Requires({ plugins: ["jQuery"],
                        js: ["jquery-ui.js", "./js/three.js", "./js/Detector.js"],
                        css: []});

  // Jos's PC WebGL kan maximaal 2048 in een richting aan
  var hpix = getQParamInt("hpix", 2048);;
  var vpix = getQParamInt("vpix", 1536);
  // Permanent inzoomen op het plaatje
  // scl: 2000 voor factor 2 enz.
  // ox en oy geven verschuiving in pixels *na* verschaling
  var scl = getQParamInt("scl", 1000);
  var ox = getQParamInt("ox", 0);
  var oy = getQParamInt("oy", 0);
  var pContmode = getQParamInt("contmode", 0);

  // 180 graden bijvoorbeeld om vanaf de andere kant te kijken
  var rot = getQParamInt("rot", 0) / 180 * Math.PI;
  var labelrot = getQParamInt("labelrot", getQParamInt("rot", 0));

  var camZ = getQParamInt("camZ", parseInt(vpix * 1.0));
  var camY = getQParamInt("camY", parseInt(- vpix / 2.0));
  var camX = getQParamInt("camX", parseInt(vpix / 2.0));

  // camX en camY automatisch met rot meeroteren
  camY = parseInt( Math.cos(rot) * camY);
  camX = parseInt( Math.sin(rot) * camX);

  // het thema voor de popup borden
  var bordlabel_key = getQParamInt("bordlabel_key", -1);

  var wallColor = getQParamInt("wallColor", 0xc0c0c0 );
  var ambientLight = getQParamInt("ambientLight", 0x999999 );
  var directionalLight = getQParamInt("directionalLight", 0xd0d0d0 );

  var symbolX = getQParamFloat( "symbolX", -1 ); // -1 kan in theorie ook een geldige waarde zijn. Ach...
  var symbolY = getQParamFloat( "symbolY", -1 );
  var symbol = getQParam("symbol", "../pictures/urhere.png");
  var showSymbol = getQParamInt("showSymbol",0)==1;

  // Muur hoogte/ breedte
  var wallw = getQParamInt("wallw", 200);
  var wallh = getQParamInt("wallh", 5 * wallw);

  if (getQParamInt("hideSymbol", 0) == 1)
    symbolX = -1;

  offsetX = ox - parseInt(hpix/2 - hpix/2/scl/1000);
  offsetY = oy - parseInt(vpix/2 + vpix/2/scl/1000);

%>
<html>
	<head>
        <% FCLTHeader.Generate(); %>
		<title>Facilitor perspective view</title>
	</head>

	<body class="floorscreen3d">

		<script>
var gSLNKEvent;
var gCustomParameters; // wat er inhoudelijk getoond moet worden (verdieping, thema's etc)
var gimgurl;

var offsetX=<%=offsetX%>;
var offsetY=<%=offsetY%>;
var scale=<%=scl%>;
var vpix = <%=vpix%>;
var hpix = <%=hpix%>;
var symbolX = <%=safe.jsfloat(symbolX)%>;
var symbolY = <%=safe.jsfloat(symbolY)%>;
var symbol = "<%=safe.jsstring(symbol)%>";

function SetCustomParameters(custParams)
{
    gCustomParameters = custParams;
}

function Refresh(actual)
{
    document.removeEventListener( 'mousedown', onDocumentMouseDown, false );  // Even geen onclicks

    init();
}

function zoom2DWG(centerX, centerY, newScale)
{
    if (!gSLNKEvent)
        return; // we waren zelf nog niet klaar.
    var currScale=vpix / (gSLNKEvent.viewmaxY - gSLNKEvent.viewminY);
    var currScale=hpix / (gSLNKEvent.viewmaxX - gSLNKEvent.viewminX);

    // zie ook CWhip2DCState::SetExtents
    var mulY =  vpix / (gSLNKEvent.DWGmaxY - gSLNKEvent.DWGminY)
    var mulX =  hpix / (gSLNKEvent.DWGmaxX - gSLNKEvent.DWGminX);

    if (mulY > mulX)
    {
        var autoMinX = gSLNKEvent.DWGminX; // als ik niets verschuif of schaal
        var autoMaxY = (gSLNKEvent.DWGminY+gSLNKEvent.DWGmaxY + vpix/mulX)/2;
    }
    else
    {
        var autoMinX = (gSLNKEvent.DWGminX+gSLNKEvent.DWGmaxX - hpix/mulY)/2;
        var autoMaxY = gSLNKEvent.DWGmaxY;
    }
    offsetX = Math.round((autoMinX - centerX) * newScale + hpix/2);
    offsetY = Math.round((centerY - autoMaxY) * newScale + vpix/2);
    scale = Math.round(1000.0 / currScale * newScale);
}
function noAutoResize()
{
}
			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();

			var SCREEN_WIDTH = window.innerWidth;
			var SCREEN_HEIGHT = window.innerHeight;

			var container;

			var camera, scene, renderer;

			//init();

            function allCast(elm)
            {
                elm.castShadow = true;
                if (elm.children)
                    for (var i in elm.children)
                        allCast(elm.children[i]);
            }

            // http://stackoverflow.com/questions/15248872/dynamically-create-2d-text-in-three-js
            var projector = new THREE.Projector();
            // image XY to canvasXY to 3D
            function toXYCoords (imgX, imgY)
            {
                    var imgPos = new THREE.Vector3(imgX - hpix / 2, vpix / 2 - imgY, 10)
                    camera.lookAt( scene.position );
    				camera.rotation.z = <%= safe.jsfloat(rot) %>;

                    camera.updateMatrixWorld();
                    var vector = projector.projectVector(imgPos.clone(), camera);
                    vector.x = (vector.x + 1)/2 * window.innerWidth;
                    vector.y = -(vector.y - 1)/2 * window.innerHeight;
                    return vector;
            }
            // 3D to canvas XY to imageXY
            function fromXYCoords (vector)
            {   var projector = new THREE.Projector();

				projector.unprojectVector( vector, camera );
                var dir = vector.sub( camera.position ).normalize();
                var distance = - camera.position.z / dir.z;
                var pos = camera.position.clone().add( dir.multiplyScalar( distance ) );

				// FcltMgr.alert("Image pos.X=" + pos.x + " pos.Y=" + pos.y);

                var imgX = pos.x + hpix / 2;
                var imgY = vpix / 2 - pos.y;
                return { x: imgX, y: imgY };
            }

			function init() {

				container = document.createElement( 'div' );

    		    document.body.appendChild( container );

				camera = new THREE.PerspectiveCamera( 35, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 10000 );

				camera.position.z = <%=camZ%>;
				camera.position.y = <%=camY%>;
                camera.position.x = <%=camX%>;

				scene = new THREE.Scene();

				// GROUND

				// PAINTING
                gimgurl = "../CAD/mySlnk2IMG.asp?labelPos=<%=S("fg_labelPosition")%>" + gCustomParameters
                           + "&sizeX="+hpix+"&sizeY="+vpix + "&labelrot=<%=labelrot%>"
                           + "&contmode=<%=pContmode%>"
                           + "&offsetX="+offsetX+"&offsetY="+offsetY+"&scale="+scale+"&paperColor=16777214";

                // 'bordlabel' wordt voor de popup 'borden' gebruikt

				var callbackPainting = function()
				{
					var image = texturePainting.image;

                    var ss = Math.min(image.width, image.height);

					var geometry = new THREE.PlaneGeometry( ss , ss );
					var mesh = new THREE.Mesh( geometry, materialPainting );

					mesh.scale.x = image.width / image.height;
					mesh.scale.y = 1;

					scene.add( mesh );

				    //mesh.receiveShadow = true;

					$.getJSON(gimgurl + "&AsMap=1",  { }, callbackWalls );
                }
                function drawBord(imgX, imgY, tekst)
                {
                    //console.log("Bord: " + tekst+  " x=" + imgX + " y=" + imgY)
                    if (!tekst) return;
                    var image = texturePainting.image;
                    var x0 = imgX;
                    var y0 = imgY;

                    tekst = tekst.replace(/\[br\]/g, "<br>");

                    var text2 = document.createElement('div');
                    text2.className = 'bord3d';
                    text2.style.position = 'absolute';
                    //text2.style.zIndex = 1;    // if you still don't see the label, try uncommenting this

                    text2.innerHTML = tekst;
                    var pos = toXYCoords(x0, y0);
                    // Eigenlijk willen we centreren maar ik weet de breedte van het bord niet.
                    text2.style.top = pos.y - 20 + "px";
                    text2.style.left = pos.x - 40 + "px";
                    container.appendChild(text2);
                }

                function drawSymbol(imgX, imgY, symbol)
                {
                    //console.log("Symbol: " + symbol+  "op x=" + imgX + " y=" + imgY)
                    var image = texturePainting.image;
                    var x0 = imgX;
                    var y0 = imgY;

                    var img = document.createElement('img');
                    img.src = symbol;
                    img.className = 'symbol3d';
                    img.style.position = 'absolute';
                    //img.style.zIndex = 1;    // if you still don't see the label, try uncommenting this

                    var imgPos = new THREE.Vector3(imgX - image.width / 2, image.height / 2 - imgY, 10)
                    var pos = toXYCoords(imgX, imgY);
                    // Eigenlijk willen we centreren maar ik weet de grootte van het symbool niet.
                    img.style.top = pos.y + "px";
                    img.style.left = pos.x + "px";
                    container.appendChild(img);
                }

                function _Centroid(coords)
                {
                    var ptx = 0;
                	var pty = 0;
                	var totArea = 0;
                	var i;
                	var arX = [], arY = [];
                	for (i = 0; i < coords.length / 2; i++)
                	{
                	    arX[i] = coords[i*2];
                	    arY[i] = coords[i*2+1];
                	}


                	for (i = 0; i < arX.length; i++) {
                		var j = (i + 1) % arX.length;
                		var dArea =  arX[i]*arY[j] - arX[j]*arY[i];
                		totArea += dArea;
                		ptx += (arX[i]+arX[j]) * dArea;
                		pty += (arY[i]+arY[j]) * dArea;
                	}
                	return { X: ptx / totArea / 3, Y: pty / totArea / 3, AREA: totArea / 2 };
                }

				var callbackWalls = function(data)
				{
				    window.gSLNKEvent = data;
                    // data.area is een heel lange string en can rect en poly's bevatten
                    //<area SLNKKey="R:12021" title="" shape="rect" coords="985,892,1079,983">
                    //<area SLNKKey="R:12023" title="" shape="poly" coords="985,738,1079,738,1079,829,985,829,985,738">
				    var areas = data.Map.split("<area");

    				// Cubes
                    var sc = <%= wallw %> / gSLNKEvent.scaleX; // muurdikte

    				var geometry = new THREE.CubeGeometry( sc, sc, sc );

                    var material = new THREE.MeshLambertMaterial( { color: <%=wallColor%>, shading: THREE.FlatShading, overdraw: true } );
    				var materialTrans = new THREE.MeshLambertMaterial( { color: <%=wallColor%>, shading: THREE.FlatShading, overdraw: true, transparent: true, opacity: 0.001 } );

    				function fromtos(arr, trans)
    				{
    				    var i;
    				    for (i=0; i < arr.length / 2 - 1; i++)
    				        fromto(arr[2*i],arr[2*i+1],arr[2*i+2],arr[2*i+3], trans)
    				}

    				function fromto(x0, y0, x1, y1, trans)
    				{
    					var cube = new THREE.Mesh( geometry, trans ? materialTrans: material );
    					//cube.castShadow = true;

    					var m = new THREE.Matrix4();
    					var rot = Math.atan( (y1-y0) / (x1-x0) )
    					m.makeRotationZ( - rot );
    					cube.applyMatrix( m );

    					// Muur hoogte
    					cube.scale.z = <%= wallh / wallw %>; // 5 keer de dikte
    					cube.position.z = cube.scale.z/2 * sc;

                        // Muur lengte
                        cube.scale.x = Math.sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0)) / sc + 1;

    					var image = texturePainting.image;
                        cube.position.x = (x0 + x1 - image.width)/ 2;
    					cube.position.y = (image.height - y0 - y1) / 2;

    					scene.add( cube );
    				}

// Werkplekken zijn ooit uitgeschakeld om 3D op IE11 te kunnen testen
// Niemand heeft het nog gemist.
    				// Werkplekken
//                  var loader = new THREE.ColladaLoader();

//                    loader.load('./models/Desk.dae.txt', function (result)
//                    {
//                      var werkplekSymbol = result.scene;
//                      allCast(werkplekSymbol);

                        // FcltMgr.alert(werkplekSymbol.scale.x); // default is 0.0254 ?
//                      werkplekSymbol.scale.set(25.4 / gSLNKEvent.scaleX , 25.4 / gSLNKEvent.scaleX, 25.4 / gSLNKEvent.scaleX);
//                      werkplekSymbol.rotation.set(0, 0, Math.PI / 4);
                        // var mat = new THREE.MeshLambertMaterial( { map: modelTex });

                      // Coordinaten werkplekken
                      $.getJSON("get_wp_info_ajax.asp?bordlabel=<%=bordlabel_key%>" + gCustomParameters,  { },
                        function (wpjson)
                            {
                                var image = texturePainting.image;
                                // FcltMgr.alert(wpjson.werkplekken.length);

                				for (var ar in areas)
                				{
                				    var area = areas[ar];
                				    if (area.indexOf("SLNKKey") < 0)
                				        continue;
                                    var key = area.substr(area.indexOf("SLNKKey=")+9, area.substr(area.indexOf("SLNKKey=")+9).indexOf("\""));

                				    // coords zitten er in <area> formaat in. Lelijke reverse-engineering:
                				    var coordsstart = area.indexOf("coords=");
                				    if (coordsstart > 0)
                				    {
                				        var coordsend = area.substr(coordsstart+8).indexOf("\"");
                				        var coords = area.substr(coordsstart+8, coordsend);
                				        if (coords.split(",").length >= 4)
                				        {
               				                var cc = coords.split(",");
               				                for (var c in cc)
               				                {
               				                    cc[c] = parseInt(cc[c], 10);
               				                }
               				                if (cc.length == 4) // dan is het een rect
               				                {
    				                            cc = [ cc[0],cc[1],cc[0],cc[3],cc[2],cc[3],cc[2],cc[1],cc[0],cc[1] ];
               				                }
               				                var found = false;
                                            for (var rm in wpjson.borden)
                                            {
                                                if (wpjson.borden[rm].key == key)
                                                {
                                                    var center = _Centroid(cc);
                                                    drawBord(center.X,center.Y, wpjson.borden[rm].tekst)
                    				            }
                    				        }
                                            for (var rm in wpjson.muren)
                                            {
                                                if (wpjson.muren[rm].key == key)
                                                {
                                                    found = true;
                    				            }
                    				        }
            				                fromtos(cc, !found); // Niet gevonden doen we transparant
                				        }
                				    }
                				}

                                if (0)
                                for (var wp in wpjson.werkplekken)
                                {
                                    var wpdata = wpjson.werkplekken[wp];
                                    var xy = toImgXY(wpdata.dwgX, wpdata.dwgY);
                                    var newModel = werkplekSymbol.clone();

                                    newModel.rotation.set(0, 0, Math.PI / 180 * wpdata.rot);
                                    newModel.position.x = (xy.imgX - image.width / 2);
    					            newModel.position.y = (image.height / 2 - xy.imgY);
                                    scene.add(newModel);
                                }

<% if (showSymbol) { %>
                                if (symbolX != -1)
                                {
                                    var xy = toImgXY(symbolX, symbolY);
                                    drawSymbol(xy.imgX, xy.imgY, symbol);
                                }
<% } %>

                                render(); // Alles klaar, renderen!!!
                        });

//                    });

    				// Lights

    				var ambientLight = new THREE.AmbientLight( <%=ambientLight%> );
    				scene.add( ambientLight );

    				var directionalLight = new THREE.DirectionalLight( <%=directionalLight%> );

    				directionalLight.position.set(800,600,1000);
    				directionalLight.position.normalize();

    				scene.add( directionalLight );

				};

                // Hier begint de echte init() code
                var png = gimgurl;
                var TIMU = THREE.ImageUtils;
                TIMU.crossOrigin = null; // Anders wordt voor de IMG-request geen ASP-session meegestuurd
                                         // door Chrome en is het plaatje direct 'expired'
				var texturePainting = TIMU.loadTexture( png, THREE.UVMapping, callbackPainting ),
					materialPainting = new THREE.MeshBasicMaterial( { color: 0xffffff, map: texturePainting } );

				renderer = new THREE.WebGLRenderer( { antialias: true } );

				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
				renderer.autoClear = false;
                renderer.shadowMapEnabled = true;

				renderer.domElement.style.position = "relative";
				container.appendChild( renderer.domElement );

				document.addEventListener('mousemove', onDocumentMouseMove, false);
				document.addEventListener('wheel', onDocumentScroll, { capture: false, passive: false });
			}

            function onDocumentScroll(e) {
                return; // Want werkt (nog) niet
                e.preventDefault();
                var delta = e.wheelDelta;
                var detail = e.detail; // Opera

                camera.position.y *= (delta <= -120 || detail > 0) ? 1.1 : (1/1.1);
                camera.position.z *= (delta <= -120 || detail > 0) ? 1.1 : (1/1.1);
            }

			function onDocumentMouseMove(event) {
                return; // Want werkt (nog) niet

				var mouseX = ( event.clientX - SCREEN_WIDTH / 2 );
				var mouseY = ( event.clientY - SCREEN_HEIGHT / 2 );
                var ctrlKey = event.ctrlKey;
				if (ctrlKey)
				{
				    camera.position.x += ( mouseX * 4 - camera.position.x ) ;
				    camera.position.y += ( - ( mouseY - 200) * 16 - camera.position.y );
				}
			}

            function callbackClicked(data)
            {
                // FcltMgr.alert(data.ContourLabel);
                data.Param = "onclick";
                parent.MMap_onClick(data);
            }
			function onDocumentMouseDown( event ) {

				event.preventDefault();

				var vector = new THREE.Vector3( ( event.clientX / window.innerWidth ) * 2 - 1, - ( event.clientY / window.innerHeight ) * 2 + 1, 0.5 );
				var xy = fromXYCoords(vector)

                var imgX = xy.x;
                var imgY = xy.y;

				// FcltMgr.alert("Image imgX=" + imgX + " imgX=" + imgY);

                $.getJSON(gimgurl + "&AsFND=1&findX=" + imgX + "&findY=" + imgY, callbackClicked );
    		}

			function render() {

				camera.lookAt( scene.position );
  				camera.rotation.z = <%= safe.jsfloat(rot) %>;

				renderer.render( scene, camera );

                // Onderstaande niet te vroeg doen, anders kloppen de coordinaten bij onclick mogelijk niet goed
				document.addEventListener( 'mousedown', onDocumentMouseDown, false );
			}

// Dee moet eigenlijk naar ToonIMG.js
function toImgXY(dwgX, dwgY)
{
    result = null;

    if (gSLNKEvent)
    {
        var result = {};
        result.scaleX = gSLNKEvent.scaleX; // DWG Size of one screen pixel X
        result.scaleY = gSLNKEvent.scaleY; // DWG Size of one screen pixel Y
        result.imgX = (dwgX - gSLNKEvent.viewminX) / result.scaleX;
        result.imgY = (gSLNKEvent.viewmaxY - dwgY) / result.scaleY;
    }
    return result;
}
		</script>

	</body>
</html>
<% ASPPAGE_END(); %> 
