Files
Facilitor/APPL/CAD/3Dize.asp
Jos Groot Lipman 6811ea0df3 Merge 2016.2 Gold C changes
svn path=/Website/trunk/; revision=31873
2016-12-07 10:46:23 +00:00

538 lines
21 KiB
Plaintext

<%@ language="javascript"%>
<% /*
$Revision$
$Id$
File: 3Dize.asp
Description:
Parameters: allerlei custom parameters
Context: Vanuit ge
Note: De tekening staat in een andere directory (S("fg_vlucht_path")) 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=2" + 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)
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("\""));
if (key.substring(0,2) == "R:") // 5.3.1 heeft dat nog niet
key = key.substr(2); // Haal de R: er af
// 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 || /*5.3.1*/ wpjson.borden[rm].rnr == 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 || /*5.3.1*/ wpjson.muren[rm].rnr == 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).on( "mousewheel DOMMouseScroll", function(e){
e.preventDefault();
var delta = e.originalEvent.wheelDelta;
var detail = e.originalEvent.detail; // FireFox
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) {
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>