Commit 5cac88b3 authored by Oleg Dzhimiev's avatar Oleg Dzhimiev

initial -db support

parent 132cc4a4
<?php
/********************************************************************************
*! FILE NAME : call_filter.php
*! DESCRIPTION: blocks direct calls, useless against fake referer.
*! VERSION: 1.0
*! AUTHOR: Oleg Dzhimiev <oleg@elphel.com>
*! Copyright (C) 2011 Elphel, Inc
*! -----------------------------------------------------------------------------**
*! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! The four essential freedoms with GNU GPL software:
*! * the freedom to run the program for any purpose
*! * the freedom to study how the program works and change it to make it do what you wish
*! * the freedom to redistribute copies so you can help your neighbor
*! * the freedom to distribute copies of your modified versions to others
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------**
*! $Log: call_filter.php,v $
*!
*/
// $check = strpos($_SERVER['HTTP_REFERER'],"http://127.0.0.1");
//
// if (($check!=0) || ($check===false)) {
// header("HTTP/1.1 404 File Not Found", 404); die();
// }
?>
\ No newline at end of file
<?php
/********************************************************************************
*! FILE NAME : copy_kml.php
*! DESCRIPTION: gets a list of kmls in the directory
*! VERSION: 1.0
*! AUTHOR: Oleg Dzhimiev <oleg@elphel.com>
*! Copyright (C) 2011 Elphel, Inc
*! -----------------------------------------------------------------------------**
*! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! The four essential freedoms with GNU GPL software:
*! * the freedom to run the program for any purpose
*! * the freedom to study how the program works and change it to make it do what you wish
*! * the freedom to redistribute copies so you can help your neighbor
*! * the freedom to distribute copies of your modified versions to others
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------**
*! $Log: copy_kml.php,v $
*!
*/
include("pano_db_functions.php");
require_once("call_filter.php");
if (!isset($_GET['proto'])) die();
if (!isset($_GET['kml'])) die();
if (count(search_kmls())>=10) die("Max file limit");
$proto = $_GET['proto'];
$kml = $_GET['kml'];
if (substr($kml,-3,3)!="kml") die();
if (is_file("kml_files/".$proto)) {
copy("kml_files/".$proto,"kml_files/".$kml);
chmod("kml_files/".$kml,0777);
echo "Done";
}else{
ConnectMySQL();
$Nodes = GetNodesByRoute($proto);
$kml_str = "";
if (isset($Nodes['error'])) {
echo "Error1";
die();
}
foreach ($Nodes as $Node) {
if (!isset($Node['error'])) $kml_str .= CreateKMLEntry($Node);
else {
send_response(CreateXMLStringFromArray($Node['error']));
die();
}
}
if ($kml_str!="") {
$result = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
$result .= "<kml xmlns=\"http://earth.google.com/kml/2.2\">\n";
$result .= "<Document>\n";
$result .= $kml_str;
$result .= "</Document></kml>";
file_put_contents("kml_files/".$kml,$result);
chmod("kml_files/".$kml,0777);
echo "Done";
}else
echo "Error";
}
?>
\ No newline at end of file
<?php
/********************************************************************************
*! FILE NAME : display_kml.php
*! DESCRIPTION: displays KML records on the page
*! VERSION: 1.0
*! AUTHOR: Oleg Dzhimiev <oleg@elphel.com>
*! Copyright (C) 2011 Elphel, Inc
*! -----------------------------------------------------------------------------**
*! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! The four essential freedoms with GNU GPL software:
*! * the freedom to run the program for any purpose
*! * the freedom to study how the program works and change it to make it do what you wish
*! * the freedom to redistribute copies so you can help your neighbor
*! * the freedom to distribute copies of your modified versions to others
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------**
*! $Log: display_kml.php,v $
*!
*/
include("pano_db_functions.php");
if (isset($_GET['id'])) $id = $_GET['id'];
else die("Error Code: 13542");
if (is_file("kml_files/".$id)) {
$content = file_get_contents("kml_files/".$id);
header("Content-Type: text/xml\n");
header("Content-Length: ".strlen($content)."\n");
header("Pragma: no-cache\n");
echo $content;
}else{
ConnectMySQL();
$Nodes = GetNodesByRoute($id);
$kml = "";
if (isset($Nodes['error'])) {
send_response("<?xml version=\"1.0\"?>\n<result><node><error>".$Nodes['error']."</error></node></result>");
die();
}
foreach ($Nodes as $Node) {
if (!isset($Node['error'])) $kml .= CreateKMLEntry($Node);
else {
send_response(CreateXMLStringFromArray($Node['error']));
die();
}
}
if ($kml!="") PrintKML2($kml);
else send_response("<?xml version=\"1.0\"?>\n<result><node><error>Some error, no apologies</error></node></result>");
}
function PrintKML2($kml) {
$content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
$content .= "<kml xmlns=\"http://earth.google.com/kml/2.2\">\n";
$content .= "<Document>\n";
$content .= $kml;
$content .= "</Document></kml>";
header("Content-Type: text/xml\n");
header("Content-Length: ".strlen($content)."\n");
header("Pragma: no-cache\n");
echo $content;
}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
<html>
<head>
<title>Eyesis Camera Model</title>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<script type="text/javascript" src="sylvester.js"></script>
<script type="text/javascript" src="glUtils.js"></script>
<script id="shader-fs" type="x-shader/x-fragment">
#ifdef GL_ES
precision highp float;
#endif
varying vec2 vTextureCoord;
varying vec3 vLightWeighting;
uniform float uAlpha; // for blending
uniform sampler2D uSampler;
void main(void) {
vec4 textureColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));
// gl_FragColor = vec4(textureColor.rgb * vLightWeighting, textureColor.a);
gl_FragColor = vec4(textureColor.rgb * vLightWeighting, textureColor.a * uAlpha);
}
</script>
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
attribute vec3 aVertexNormal;
attribute vec2 aTextureCoord;
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
uniform mat4 uNMatrix;
uniform vec3 uAmbientColor; ////
uniform vec3 uLightingDirection; ////
uniform vec3 uDirectionalColor; ////
uniform bool uUseLighting; ////
varying vec2 vTextureCoord;
varying vec3 vLightWeighting;
void main(void) {
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
vTextureCoord = aTextureCoord;
if (!uUseLighting) {////
vLightWeighting = vec3(1.0, 1.0, 1.0);////
} else {////
vec4 transformedNormal = uNMatrix * vec4(aVertexNormal, 1.0);////
float directionalLightWeighting = max(dot(transformedNormal.xyz, uLightingDirection), 0.0);////
vLightWeighting = uAmbientColor + uDirectionalColor * directionalLightWeighting;////
}////
}
</script>
<script type="text/javascript">
var gl;
function initGL(canvas) {
try {
gl = canvas.getContext("experimental-webgl");
gl.viewportWidth = canvas.width;
gl.viewportHeight = canvas.height;
} catch(e) {
}
if (!gl) {
alert("Could not initialise WebGL, sorry :-(");
}
}
function getShader(gl, id) {
var shaderScript = document.getElementById(id);
if (!shaderScript) {
return null;
}
var str = "";
var k = shaderScript.firstChild;
while (k) {
if (k.nodeType == 3) {
str += k.textContent;
}
k = k.nextSibling;
}
var shader;
if (shaderScript.type == "x-shader/x-fragment") {
shader = gl.createShader(gl.FRAGMENT_SHADER);
} else if (shaderScript.type == "x-shader/x-vertex") {
shader = gl.createShader(gl.VERTEX_SHADER);
} else {
return null;
}
gl.shaderSource(shader, str);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert(gl.getShaderInfoLog(shader));
return null;
}
return shader;
}
var shaderProgram;
function initShaders() {
var fragmentShader = getShader(gl, "shader-fs");
var vertexShader = getShader(gl, "shader-vs");
shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert("Could not initialise shaders");
}
gl.useProgram(shaderProgram);
shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord");
gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute);
shaderProgram.vertexNormalAttribute = gl.getAttribLocation(shaderProgram, "aVertexNormal");
gl.enableVertexAttribArray(shaderProgram.vertexNormalAttribute);
shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
shaderProgram.nMatrixUniform = gl.getUniformLocation(shaderProgram, "uNMatrix");
shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler");
shaderProgram.alphaUniform = gl.getUniformLocation(shaderProgram, "uAlpha");
shaderProgram.useLightingUniform = gl.getUniformLocation(shaderProgram, "uUseLighting"); ////
shaderProgram.ambientColorUniform = gl.getUniformLocation(shaderProgram, "uAmbientColor"); ////
shaderProgram.lightingDirectionUniform = gl.getUniformLocation(shaderProgram, "uLightingDirection"); ////
shaderProgram.directionalColorUniform = gl.getUniformLocation(shaderProgram, "uDirectionalColor"); ////
}
function handleLoadedTexture(texture) {
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.image);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.bindTexture(gl.TEXTURE_2D, null);
}
var eyesisTextureSrc =[ "eyesis.jpeg","eyesis_grey.jpeg","eyesis_selected.jpeg"];
var eyesisTexture = Array(eyesisTextureSrc.length);
function initTexture() {
initEyesisTexture();
}
function initEyesisTexture() {
for (var i=0;i<eyesisTextureSrc.length;i++) {
eyesisTexture[i] = gl.createTexture();
eyesisTexture[i].image = new Image();
eyesisTexture[i].image.index = i;
eyesisTexture[i].image.onload = function() {
handleLoadedTexture(eyesisTexture[this.index])
}
eyesisTexture[i].image.src = eyesisTextureSrc[i];
}
}
var mvMatrix;
var mvMatrixStack = [];
function mvPushMatrix(m) {
if (m) {
mvMatrixStack.push(m.dup());
mvMatrix = m.dup();
} else {
mvMatrixStack.push(mvMatrix.dup());
}
}
function mvPopMatrix() {
if (mvMatrixStack.length == 0) {
throw "Invalid popMatrix!";
}
mvMatrix = mvMatrixStack.pop();
return mvMatrix;
}
function loadIdentity() {
mvMatrix = Matrix.I(4);
}
function multMatrix(m) {
mvMatrix = mvMatrix.x(m);
}
function mvTranslate(v) {
var m = Matrix.Translation($V([v[0], v[1], v[2]])).ensure4x4();
multMatrix(m);
}
function createRotationMatrix(angle, v) {
var arad = angle * Math.PI / 180.0;
return Matrix.Rotation(arad, $V([v[0], v[1], v[2]])).ensure4x4();
}
function mvRotate(angle, v) {
multMatrix(createRotationMatrix(angle, v));
}
var pMatrix;
function perspective(fovy, aspect, znear, zfar) {
pMatrix = makePerspective(fovy, aspect, znear, zfar);
}
function setMatrixUniforms() {
gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, new Float32Array(pMatrix.flatten()));
gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, new Float32Array(mvMatrix.flatten()));
var normalMatrix = mvMatrix.inverse();
normalMatrix = normalMatrix.transpose();
gl.uniformMatrix4fv(shaderProgram.nMatrixUniform, false, new Float32Array(normalMatrix.flatten()));
}
var mouseDown = false;
var lastMouseX = null;
var lastMouseY = null;
var eyesisRotationMatrix = Matrix.I(4);
function handleMouseDown(event) {
mouseDown = true;
lastMouseX = event.clientX;
lastMouseY = event.clientY;
}
function handleMouseUp(event) {
mouseDown = false;
}
function handleMouseMove(event) {
if (!mouseDown) {
return;
}
var newX = event.clientX;
var newY = event.clientY;
var deltaX = newX - lastMouseX
var newRotationMatrix = createRotationMatrix(deltaX / 10, [0, 1, 0]);
var deltaY = newY - lastMouseY;
newRotationMatrix = newRotationMatrix.x(createRotationMatrix(deltaY / 10, [1, 0, 0]));
eyesisRotationMatrix = newRotationMatrix.x(eyesisRotationMatrix);
lastMouseX = newX
lastMouseY = newY;
}
function initBuffers() {
initBuffersEyesis();
}
var eyesisVertexPositionBuffer;
var eyesisVertexNormalBuffer;
var eyesisVertexTextureCoordBuffer;
var eyesisVertexIndexBuffer;
function initBuffersEyesis() {
var divs=8; // 2 - shade separator (21mm), 6 - hole (60mm) for each camera
var subDivs=4; //8; //2; // subdivide each unit (see above) for smooth cylinder
var symmetry=8; // number of camera modules
var allDivs=subDivs*divs;
var scale =0.001; // mm/m
var cavityIndex=20; // 9; // next 6
var cavityHeight=22; //5; // (not counting points on the edge
var angleFin=0.01; //half angle thickness of a fin, radians
var deltaR1=2; // outer shade walls
var deltaR2=45;// distance to side filters from the outer shade
var topBottomThickness=2;
var cavityLong= subDivs+1; // +/-
var cylinderPoints = [ // axis, radius
70.625,0, // 0
70.625,40, // 1
70.625,40, // 2
40.75, 40, // 3
40.75,40, // 4
40.75, 55, // 5
40.75,55, // 6
79.25, 55, // 7
79.25,55, // 8
79.25, 50, // 9
79.25,50, //10
80.75, 50, //11
80.75,50, //12
80.75,62.6, //13
80.75,62.6, //14
59.5, 62.6, //15
59.5, 62.6, //16
59.5, 105, //17
59.5, 105, //18
46.5, 105, //19
30, 105, // needed for the side lens cavity 18
25, 105, // needed for the side lens cavity 19
20, 105, // needed for the side lens cavity 20
// extra divisions to increase the size of the lens part
16, 105, // needed for the side lens cavity 21
14, 105, // needed for the side lens cavity 22
12, 105, // needed for the side lens cavity 23
10, 105, // needed for the side lens cavity 24
8, 105, // needed for the side lens cavity 25
6, 105, // needed for the side lens cavity 26
4, 105, // needed for the side lens cavity 27
2, 105, // needed for the side lens cavity 28
0, 105, // needed for the side lens cavity 29
-2, 105, // needed for the side lens cavity 30
-4, 105, // needed for the side lens cavity 31
-6, 105, // needed for the side lens cavity 32
-8, 105, // needed for the side lens cavity 33
-10, 105, // needed for the side lens cavity 34
-12, 105, // needed for the side lens cavity 35
-14, 105, // needed for the side lens cavity 36
-16, 105, // needed for the side lens cavity 37
-20, 105, // needed for the side lens cavity 38
-25, 105, // needed for the side lens cavity 39
-30, 105, // needed for the side lens cavity 40
-47.5, 105, // 41
-61.5, 105, // 42
-61.5, 105, // 43
-61.5, 54.1, // 44
-61.5, 54.1, // 45
-168.95, 54.1, // 46
-168.95,54.1, // 47
-171.25, 56.4, // 48
-171.25,56.4, // 49
-184.25, 56.4, // 50
-184.25,56.4, // 51
-185.75, 59.5, // 52
-185.75,59.5, // 53
-191.25, 59.5, // 54
-191.25,59.5, // 55
-251.25, 32.5, // 56
-251.25,32.5, // 57
-251.25, 30.1625,//58
-251.25,30.1625,//59
-1000, 30.1625 //60
];
var latitudeBands = cylinderPoints.length/2-1;
var longitudeBands = allDivs*symmetry;
var vertexPositionData = [];
var textureCoordData = [];
for (var latNumber = 0; latNumber <= latitudeBands; latNumber++) {
var h0=cylinderPoints[2*latNumber]*scale;
var r0=cylinderPoints[2*latNumber+1]*scale;
var symLong;
for (var longNumber = 0; longNumber <= longitudeBands; longNumber++) {
var r=r0;
var h=h0;
var phi = longNumber * 2 * Math.PI / longitudeBands;
symLong= longNumber-allDivs*Math.floor(longNumber/allDivs);
if (symLong>(allDivs/2)) symLong=allDivs-symLong;
var v = 1 - (latNumber / latitudeBands);
var u = 1 - 2*(symLong / allDivs);
if ((latNumber>=cavityIndex) && (latNumber<= (cavityIndex+cavityHeight)) && (symLong>=cavityLong)) {
var longNum0=allDivs*Math.floor(longNumber/allDivs); // number of longitude steps till the beginning of this module
var longNum1=longNumber-longNum0; // number of longitude steps since the beginning of this module
var phi0 = longNum0 * 2 * Math.PI / longitudeBands; // angle at the beginning of this module
var phi0a=phi0+ (cavityLong-1)*2 * Math.PI / longitudeBands; // angle at the outer edge of this module
var phi0b=phi0+angleFin;
var phi1 = (longNum0 + allDivs )* 2 * Math.PI / longitudeBands; // angle at the beginning of this module
var phi1a=phi1-(cavityLong-1)*2 * Math.PI / longitudeBands; // angle at the outer edge of this module
var phi1b=phi1-angleFin;
if (longNum1<=(cavityLong+1)) phi=phi0a;
else if (longNum1>=(allDivs-cavityLong-1)) phi=phi1a;
else if (longNum1==(cavityLong+2)) phi=phi0b;
else if (longNum1==(allDivs-cavityLong-2)) phi=phi1b;
else phi=phi0b+(phi1b-phi0b)*(longNum1-cavityLong-3)/(allDivs-2*cavityLong-6);
if ((symLong==cavityLong) || (latNumber== cavityIndex) || (latNumber==(cavityIndex+cavityHeight))) r=r0;
else if ((symLong==(cavityLong+1)) || (symLong==(cavityLong+2) ||
(latNumber== (cavityIndex+1)) ||
(latNumber==(cavityIndex+2)) ||
(latNumber==(cavityIndex+cavityHeight-2)) ||
(latNumber==(cavityIndex+cavityHeight-1)))) r=r0-deltaR1*scale;
else r=r0-deltaR2*scale;
if (latNumber<= (cavityIndex+1)) h=cylinderPoints[2*(cavityIndex-1)]*scale;
else if (latNumber>= (cavityIndex+cavityHeight-1)) h=cylinderPoints[2*(cavityIndex+cavityHeight+1)]*scale;
else if (latNumber== (cavityIndex+2)) h=(cylinderPoints[2*(cavityIndex-2)]-topBottomThickness)*scale;
else if (latNumber== (cavityIndex+cavityHeight-2)) h=(cylinderPoints[2*(cavityIndex+cavityHeight+2)]+topBottomThickness)*scale;
else h= (((cylinderPoints[2*(cavityIndex-2)]-topBottomThickness)*scale)* (cavityIndex+cavityHeight-3-latNumber)+
((cylinderPoints[2*(cavityIndex+cavityHeight+2)]+topBottomThickness)*scale)* (latNumber-(cavityIndex+3)))/(cavityHeight-6);
}
var sinPhi = Math.sin(phi);
var cosPhi = Math.cos(phi);
var x = cosPhi * r;
var y = h;
var z = sinPhi * r;
textureCoordData.push(u);
textureCoordData.push(v);
vertexPositionData.push(x);
vertexPositionData.push(y);
vertexPositionData.push(z);
}
}
// Handling normalData - average normals connected to the vertex, proportionally to the angles of the triangles connected to it (if it is non-zero)
// even different - angle*area, so for the smooth rectangular mesh there will be the same contribution for the "90-degree" and a pair of the "45-degree" ones
var normalData = Array(vertexPositionData.length);
var normalMaxSize = Array(vertexPositionData.length/3);
for (var i=0;i<normalMaxSize.length;i++) normalMaxSize[i]=0;
for (var i=0;i<normalData.length;i++) normalData[i]=0;
var indexData = [];
for (var latNumber = 0; latNumber < latitudeBands; latNumber++) {
for (var longNumber = 0; longNumber < longitudeBands; longNumber++) {
var first = (latNumber * (longitudeBands + 1)) + longNumber;
var second = first + longitudeBands + 1;
// Split quadrilateral into 2 triangles so the total area will be minimal
var F =[vertexPositionData[3*first+0], vertexPositionData[3*first+1], vertexPositionData[3*first+2]];
var S =[vertexPositionData[3*second+0],vertexPositionData[3*second+1],vertexPositionData[3*second+2]];
var F1=[vertexPositionData[3*first+3], vertexPositionData[3*first+4], vertexPositionData[3*first+5]];
var S1=[vertexPositionData[3*second+3],vertexPositionData[3*second+4],vertexPositionData[3*second+5]];
var SF= [S[0]- F[0], S[1]- F[1], S[2]- F[2]];
var F1F= [F1[0]- F[0], F1[1]- F[1], F1[2]- F[2]];
var S1S= [S1[0]- S[0], S1[1]- S[1], S1[2]- S[2]];
var S1F1=[S1[0]-F1[0], S1[1]-F1[1], S1[2]-F1[2]];
var nFSF1= vmul(SF,F1F);
var nSS1F1= vmul(S1F1,S1S);
var nFSS1= vmul(SF,S1S);
var nFS1F1= vmul(S1F1,F1F);
var aFSF1= abs3(nFSF1);
var aSS1F1= abs3(nSS1F1);
var aFSS1= abs3(nFSS1);
var aFS1F1= abs3(nFS1F1);
var vIndices, normals, areas, vIndex;
if ((aFSF1+aSS1F1)>(aFSS1+aFS1F1)){
vIndices= [[first,second+1,first+1],[first,second,second+1]];
normals=[unityVector3(nFS1F1),unityVector3(nFSS1)];
areas= [aFS1F1,aFSS1];
} else {
vIndices= [[first,second,first+1],[second,second+1,first+1]];
normals=[unityVector3(nFSF1),unityVector3(nSS1F1)];
areas=[aFSF1,aSS1F1];
}
for (var i=0;i<2;i++) {
if (areas[i]>0.0) for (var j=0;j<3;j++) {
indexData.push(vIndices[i][j]);
}
}
for (var i=0;i<2;i++) if (areas[i]>0) for (var j=0;j<3;j++) {
var indx0=vIndices[i][j];
var indx1=vIndices[i][(j+1)%3];
var indx2=vIndices[i][(j+2)%3];
var l1=abs3([vertexPositionData[3*indx1+0]-vertexPositionData[3*indx0+0],
vertexPositionData[3*indx1+1]-vertexPositionData[3*indx0+1],
vertexPositionData[3*indx1+2]-vertexPositionData[3*indx0+2]]);
var l2=abs3([vertexPositionData[3*indx2+0]-vertexPositionData[3*indx0+0],
vertexPositionData[3*indx2+1]-vertexPositionData[3*indx0+1],
vertexPositionData[3*indx2+2]-vertexPositionData[3*indx0+2]]);
var sinAngle=areas[i]/l1/l2;
if (sinAngle>1.0) sinAngle=1.0;
else if (sinAngle<-1.0) sinAngle=-1.0;
var angle=Math.abs(Math.asin(sinAngle)); // Do we need Math.abs() nere?
var w=angle*areas[i];
normalData[3*indx0+0]-=normals[i][0]*w;
normalData[3*indx0+1]-=normals[i][1]*w;
normalData[3*indx0+2]-=normals[i][2]*w;
}
}
}
for (var i=0; i<normalData.length; i+=3) {
var v=[normalData[i],normalData[i+1],normalData[i+2]];
var l=abs3(v);
for (var j=i; j<i+3;j++) normalData[j]/=l;
}
//document.title="indexData.length="+indexData.length;
eyesisVertexNormalBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, eyesisVertexNormalBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(normalData), gl.STATIC_DRAW);
eyesisVertexNormalBuffer.itemSize = 3;
eyesisVertexNormalBuffer.numItems = normalData.length / 3;
eyesisVertexTextureCoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, eyesisVertexTextureCoordBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoordData), gl.STATIC_DRAW);
eyesisVertexTextureCoordBuffer.itemSize = 2;
eyesisVertexTextureCoordBuffer.numItems = textureCoordData.length / 2;
eyesisVertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, eyesisVertexPositionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexPositionData), gl.STATIC_DRAW);
eyesisVertexPositionBuffer.itemSize = 3;
eyesisVertexPositionBuffer.numItems = vertexPositionData.length / 3;
eyesisVertexIndexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, eyesisVertexIndexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indexData), gl.STREAM_DRAW);
eyesisVertexIndexBuffer.itemSize = 1;
eyesisVertexIndexBuffer.numItems = indexData.length;
}
function vmul(a,b) {
return [a[1]*b[2]-a[2]*b[1], a[2]*b[0]-a[0]*b[2], a[0]*b[1]-a[1]*b[0]];
}
function area(a,b) {
var v=vmul(a,b);
return Math.sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
}
function abs3(v) {
return Math.sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
}
function unityVector3(v) {
l=Math.sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
if (l==0) return [0,0,0];
else return [v[0]/l,v[1]/l,v[2]/l];
}
var dist=-.4;
var distStep=0.01;
function drawEyesis(x,y,z, alpha, index, this_lighting) {
var lighting = document.getElementById("lighting").checked; ////
gl.uniform1i(shaderProgram.useLightingUniform, lighting && this_lighting); ////
if (lighting && this_lighting) { ////
gl.uniform3f( ////
shaderProgram.ambientColorUniform, ////
parseFloat(document.getElementById("ambientR").value), ////
parseFloat(document.getElementById("ambientG").value), ////
parseFloat(document.getElementById("ambientB").value) ////
); ////
var elevation=parseFloat(document.getElementById("lightElevatrion").value)*Math.PI/180;
var cosElevation=Math.cos(elevation);
var azimuth=parseFloat(document.getElementById("lightAzimuth").value)*Math.PI/180;
var lightSourceDirection=[Math.sin(azimuth)*cosElevation,Math.sin(elevation),-Math.cos(azimuth)*cosElevation];
//document.title="["+lightSourceDirection[0]+", "+ lightSourceDirection[1]+", "+ lightSourceDirection[2]+"]";
gl.uniform3f(shaderProgram.lightingDirectionUniform,lightSourceDirection[0],lightSourceDirection[1],lightSourceDirection[2]);
gl.uniform3f( ////
shaderProgram.directionalColorUniform, ////
parseFloat(document.getElementById("directionalR").value), ////
parseFloat(document.getElementById("directionalG").value), ////
parseFloat(document.getElementById("directionalB").value) ////
); ////
} ////
loadIdentity();
// mvTranslate([0, 0, -6]);
// mvTranslate([0, 0, dist]);
mvTranslate([x,y,z]);
multMatrix(eyesisRotationMatrix); // same for both
setMatrixUniforms();
if (alpha>0) {
gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
gl.enable(gl.BLEND);
gl.disable(gl.DEPTH_TEST);
gl.uniform1f(shaderProgram.alphaUniform, alpha);
} else {
gl.disable(gl.BLEND);
gl.enable(gl.DEPTH_TEST);
gl.uniform1f(shaderProgram.alphaUniform, 1.0);
}
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, eyesisTexture[index]);
gl.uniform1i(shaderProgram.samplerUniform, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, eyesisVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, eyesisVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, eyesisVertexTextureCoordBuffer);
gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, eyesisVertexTextureCoordBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, eyesisVertexNormalBuffer);
gl.vertexAttribPointer(shaderProgram.vertexNormalAttribute, eyesisVertexNormalBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, eyesisVertexIndexBuffer);
gl.drawElements(gl.TRIANGLES, eyesisVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
// gl.lineWidth(1);
// gl.drawElements(gl.LINE_STRIP, eyesisVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
}
function drawScene() {
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
perspective(45, gl.viewportWidth / gl.viewportHeight, 0.01, 100.0);
gl.uniform1i(shaderProgram.useLightingUniform, false);
drawEyesis(-.5, 0, -1, 0, 1,false);
drawEyesis(-.5, 0,dist,.5, 2,false);
drawEyesis(-1, 0,dist, 0, 1,true);
drawEyesis( 0, 0,dist, 0, 0,true);
drawEyesis(.5, 0,dist, 0, 2,false);
drawEyesis(1, 0,dist, 0, 1,true);
// drawEyesis(-3,false);
// drawEyesis(dist,false);
}
function tick() {
drawScene();
}
function webGLStart() {
var canvas = document.getElementById("lesson11-canvas");
initGL(canvas);
initShaders();
initBuffers();
initTexture();
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clearDepth(1.0);
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
canvas.onmousedown = handleMouseDown;
document.onmouseup = handleMouseUp;
document.onmousemove = handleMouseMove;
if (window.addEventListener)
window.addEventListener('DOMMouseScroll', wheelEvent, false);
window.onmousewheel = document.onmousewheel = wheelEvent;
setInterval(tick, 15);
}
function wheelEvent(event){
var delta = 0;
if (!event) event = window.event; // IE
if (event.wheelDelta) { //IE+Opera
delta = event.wheelDelta/120;
if (window.opera) delta = -delta;
} else if (event.detail) { // Mozilla
delta = -event.detail/3;
}
if (delta)
handleWheel(delta);
if (event.preventDefault)
event.preventDefault();
event.returnValue = false;
}
function handleWheel(delta) {
dist+=distStep*delta;
drawScene();
}
</script>
</head>
<body onload="webGLStart();">
<canvas id="lesson11-canvas" style="border: none;" width="1500" height="800"></canvas>
<br/>
<input id="lighting" checked="checked" type="checkbox"/> Use lighting<br/>
<br>
<h2>Directional light:</h2>
<table style="border: 0pt none; padding: 10px;">
<tbody><tr>
<td><b>Direction:</b></td>
<td>Azimuth: <input id="lightAzimuth" value="225" type="text"></td>
<td>Elevation: </td><td><input id="lightElevatrion" value="45" type="text"></td></tr>
<tr>
<td><b>Colour:</b>
</td><td>R: <input id="directionalR" value=".8" type="text">
</td><td>G: <input id="directionalG" value=".8" type="text">
</td><td>B: <input id="directionalB" value=".8" type="text">
</td></tr>
</tbody></table>
<h2>Ambient light:</h2>
<table style="border: 0pt none; padding: 10px;">
<tbody><tr>
<td><b>Colour:</b>
</td><td>R: <input id="ambientR" value="0.2" type="text">
</td><td>G: <input id="ambientG" value="0.2" type="text">
</td><td>B: <input id="ambientB" value="0.2" type="text">
</td></tr>
</tbody></table>
</body>
</html>
<?php
/********************************************************************************
*! FILE NAME : filelist.php
*! DESCRIPTION: gets a list of kmls in the directory
*! VERSION: 1.0
*! AUTHOR: Oleg Dzhimiev <oleg@elphel.com>
*! Copyright (C) 2011 Elphel, Inc
*! -----------------------------------------------------------------------------**
*! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! The four essential freedoms with GNU GPL software:
*! * the freedom to run the program for any purpose
*! * the freedom to study how the program works and change it to make it do what you wish
*! * the freedom to redistribute copies so you can help your neighbor
*! * the freedom to distribute copies of your modified versions to others
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------**
*! $Log: filelist.php,v $
*!
*/
require_once("call_filter.php");
//$type = $_GET["type"];
$type = "kml";
$filelist = scandir("kml_files/");
$pre_res_xml="";
foreach ($filelist as $value) {
//printf($value."\n");
process_folder($value,$type);
}
flush_xml($pre_res_xml);
function process_folder($file,$type) {
global $pre_res_xml;
$ext=get_file_extension("kml_files/".$file);
// exclude "." & ".."
if ($ext==$type && (substr($file,0,1)!=".")) {
$pre_res_xml .= "<f>$file</f>\n";
}
}
function get_file_extension($filename) {
//return substr(strrchr($filename, '.'), 1);
return pathinfo($filename, PATHINFO_EXTENSION);
}
function flush_xml($pre_res_xml) {
$res_xml = "<?xml version='1.0' standalone='yes'?>\n";
$res_xml .="<folder_list>\n";
$res_xml .= $pre_res_xml;
$res_xml .="</folder_list>\n";
header("Content-Type: text/xml");
header("Content-Length: ".strlen($res_xml)."\n");
header("Pragma: no-cache\n");
printf("%s", $res_xml);
flush();
}
?>
\ No newline at end of file
[Dolphin]
PreviewsShown=true
SortOrder=1
SortRole=date
Sorting=2
Timestamp=2016,12,27,10,45,34
Version=3
ViewMode=1
body{
font-family:"Times New Roman", Times, serif;
}
button {
font-family:"Times New Roman", Times, serif;
border: 0px solid black;
font-size: 16px;
/*line-height: 24px;*/
padding: 3px 20px 3px 20px;
/*border radius*/
border-radius: 5px;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
/*shadow*/
-moz-box-shadow: 1px 1px 1px gray;
-webkit-box-shadow: 1px 1px 1px gray;
box-shadow: 1px 1px 1px gray;
/*text-shadow: 1px 1px 1px gray;*/
color: rgba(60,60,60,1);
text-align:center;
/*remove text selection*/
/* -webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-o-user-select: none;
user-select: none;*/
}
button:active {
text-shadow: 0px 0px 0px gray;
color: rgba(100,100,100,1);
/*shadow*/
-moz-box-shadow: 0px 0px 0px gray;
-webkit-box-shadow: 0px 0px 0px gray;
box-shadow: 0px 0px 0px gray;
}
button:hover{
/* -moz-box-shadow: 0px 0px 10px black;
-webkit-box-shadow: 0px 0px 10px black;
box-shadow: 0px 0px 10px black; */
}
/*background gradients*/
button {
background: -webkit-gradient(linear, left top, left bottom, from(rgba(100,200,100,0.7)), to(rgba(100,200,100,0.7))); /* for webkit browsers */
background: -moz-linear-gradient(top, rgba(100,200,100,0.7), rgba(100,200,100,0.7)); /* for firefox 3.6+ */
}
button:hover {
background: -webkit-gradient(linear, left top, left bottom, from(rgba(170,256,170,1)), to(rgba(130,230,130,1))); /* for webkit browsers */
background: -moz-linear-gradient(top, rgba(170,256,170,1), rgba(130,230,130,1)); /* for firefox 3.6+ */
}
button:active {
background: -webkit-gradient(linear, left top, left bottom, from(rgba(200,200,200,1)), to(rgba(150,150,150,1))); /* for webkit browsers */
background: -moz-linear-gradient(top, rgba(200,200,200,1), rgba(150,150,150,1)); /* for firefox 3.6+ */
}
.input_text {
border: 0px solid black;
/*line-height: 22px;*/
width: 100px;
height: 24px;
-moz-line-height: 22px;
border-radius: 3px;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
}
files/dot.png

406 Bytes

/*
*! -----------------------------------------------------------------------------**
*! FILE NAME : dots.js
*! REVISION : 1.0
*! DESCRIPTION: draw lines webgl procedures (originate from drawing arrows)
*! Copyright (C) 2011 Elphel, Inc.
*!
*! -----------------------------------------------------------------------------**
*! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*!
*! It means that the program's users have the four essential freedoms:
*!
*! * The freedom to run the program, for any purpose (freedom 0).
*! * The freedom to study how the program works, and change it to make it do what you wish (freedom 1).
*! Access to the source code is a precondition for this.
*! * The freedom to redistribute copies so you can help your neighbor (freedom 2).
*! * The freedom to distribute copies of your modified versions to others (freedom 3).
*!
*! By doing this you can give the whole community a chance to benefit from your changes.
*! Access to the source code is a precondition for this.
*! -----------------------------------------------------------------------------**
*/
var dotTexture;
var dotVertexPositionBuffer;
var dotVertexPositionBuffer2;
var dotVertexIndexBuffer;
var dotVertexTextureCoordBuffer;
var dotVertexNormalBuffer;
function handleLoadedDotTexture(texture) {
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.image);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.bindTexture(gl.TEXTURE_2D, null);
}
function initDotTexture() {
dotTexture = gl.createTexture();
dotTexture.image = new Image();
dotTexture.image.onload = function() {
handleLoadedDotTexture(dotTexture)
}
dotTexture.image.src = "files/dot.png";
}
function initDotBuffers() {
dotVertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, dotVertexPositionBuffer);
var vertices = [
-1, 0, 0.0,
-1, 0, 0.0,
-1, 0, 0.0,
-1, 0, 0.0,
1, 0, 0.0,
1, 0, 0.0,
1, 0, 0.0
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
dotVertexPositionBuffer.itemSize = 3;
dotVertexPositionBuffer.numItems = 7;
dotVertexPositionBuffer2 = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, dotVertexPositionBuffer2);
var vertices2 = [
0, -1, 0.0,
0, -1, 0.0,
0, -1, 0.0,
0, -1, 0.0,
0, 1, 0.0,
0, 1, 0.0,
0, 1, 0.0
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices2), gl.STATIC_DRAW);
dotVertexPositionBuffer2.itemSize = 3;
dotVertexPositionBuffer2.numItems = 7;
dotVertexTextureCoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, dotVertexTextureCoordBuffer);
var textureCoords = [
1.0, 1.0,
1.0, 1.0,
1.0, 1.0,
1.0, 0.0,
0.0, 0.0,
0.0, 1.0,
0.0, 1.0
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoords), gl.STATIC_DRAW);
dotVertexTextureCoordBuffer.itemSize = 2;
dotVertexTextureCoordBuffer.numItems = 7;
dotVertexNormalBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, dotVertexNormalBuffer);
var vertexNormals = [
0.0, 1.0, 0.0,
0.0, 1.0, 0.0,
0.0, 1.0, 0.0,
0.0, 1.0, 0.0,
0.0, 1.0, 0.0,
0.0, 1.0, 0.0,
0.0, 1.0, 0.0
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexNormals), gl.STATIC_DRAW);
dotVertexNormalBuffer.itemSize = 3;
dotVertexNormalBuffer.numItems = 7;
dotVertexIndexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, dotVertexIndexBuffer);
var dotVertexIndices = [
0, 1, 6,
5, 2, 3,
5, 3, 4
]
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(dotVertexIndices), gl.STATIC_DRAW);
dotVertexIndexBuffer.itemSize = 1;
dotVertexIndexBuffer.numItems = 9;
}
function drawLine(axis,angle,down, distance,someVertexPositionBuffer) {
loadIdentity();
var axisMatrix = createRotationMatrix(angle, [axis.e(1), axis.e(2), axis.e(3)]);
multMatrix(axisMatrix);
mvTranslate([0.0, -down, -distance]);
setMatrixUniforms();
gl.uniform1f(shaderProgram.alphaUniform, 1.0);
gl.disable(gl.BLEND);
gl.enable(gl.DEPTH_TEST);
gl.uniform1f(shaderProgram.alphaUniform, 1.0);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, dotTexture);
gl.uniform1i(shaderProgram.samplerUniform, 0);
gl.lineWidth(3);
gl.bindBuffer(gl.ARRAY_BUFFER, dotVertexTextureCoordBuffer);
gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, dotVertexTextureCoordBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, dotVertexNormalBuffer);
gl.vertexAttribPointer(shaderProgram.vertexNormalAttribute, dotVertexNormalBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, someVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, someVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, dotVertexIndexBuffer);
gl.drawElements(gl.LINE_STRIP, dotVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
}
\ No newline at end of file
/*
*! -----------------------------------------------------------------------------**
*! FILE NAME : extras.js
*! REVISION : 1.0
*! DESCRIPTION: additional funcions for maps, blinking (to be moved somewhere else later)
*! Copyright (C) 2011 Elphel, Inc.
*!
*! -----------------------------------------------------------------------------**
*! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*!
*! It means that the program's users have the four essential freedoms:
*!
*! * The freedom to run the program, for any purpose (freedom 0).
*! * The freedom to study how the program works, and change it to make it do what you wish (freedom 1).
*! Access to the source code is a precondition for this.
*! * The freedom to redistribute copies so you can help your neighbor (freedom 2).
*! * The freedom to distribute copies of your modified versions to others (freedom 3).
*!
*! By doing this you can give the whole community a chance to benefit from your changes.
*! Access to the source code is a precondition for this.
*! -----------------------------------------------------------------------------**
*/
var osm_CurrentMarker;
function initialize_maps() {
// why did I use range here?
var url=serverURL+"?kml="+settings.kml+"&range="+settings.range;
//var url=serverURL+"?kml="+settings.kml;
if (settings.mask!="") url+="&mask="+settings.mask; // use second KML file to overwrite main KML file settings
//if (settings.map!="") url+="&map="+settings.map;
url+="&map=all";
//if (settings.start!="") url+="&href="+settings.start+"&range="+settings.range;
if (settings.start!="") url+="&href="+settings.start;
if ((typeof(settings.proto)!="undefined") && (settings.proto!="")) url+="&proto="+settings.proto; // use this KML file as a prototype for kml= (copy to kml if kml does not exist)
$("#map_header").trigger('click');
$("#osmap_header").trigger('click');
requestKml(url,place_points);
//requestKml(serverURL+"?kml="+settings.kml,place_points);
/*toggle_gmap();
toggle_osmap(); */
}
function initialize_maps_nowebgl() {
var url=serverURL+"?kml="+settings.kml+"&range="+settings.range;
if (settings.mask!="") url+="&mask="+settings.mask; // use second KML file to overwrite main KML file settings
//if (settings.map!="") url+="&map="+settings.map;
url+="&map=all";
//if (settings.start!="") url+="&href="+settings.start+"&range="+settings.range;
if (settings.start!="") url+="&href="+settings.start;
if ((typeof(settings.proto)!="undefined") && (settings.proto!="")) url+="&proto="+settings.proto; // use this KML file as a prototype for kml= (copy to kml if kml does not exist)
$("#map_header").trigger('click');
$("#osmap_header").trigger('click');
requestKml(url,place_points_nowebgl);
//requestKml(serverURL+"?kml="+settings.kml,place_points);
/*toggle_gmap();
toggle_osmap(); */
}
function loading_blink(){
var d = new Date();
var curr_sec = d.getSeconds();
if (curr_sec%4==1) {
document.getElementById('status').style.color = "white";
document.getElementById('status').innerHTML = "Loading.";
}
else if (curr_sec%4==2) {
document.getElementById('status').style.color = "black";
document.getElementById('status').innerHTML = "Loading..";
}
else if (curr_sec%4==3) {
document.getElementById('status').style.color = "white";
document.getElementById('status').innerHTML = "Loading...";
}
else {
document.getElementById('status').style.color = "black";
document.getElementById('status').innerHTML = "Loading";
}
}
function pre_loading_blink() {
var top = window.innerHeight;
var left = window.innerWidth;
top = top/2;
left = left/2;
document.getElementById('status').style.top = top - $('#status').height()/2;
document.getElementById('status').style.left = left - $('#status').width()/2;
$("#status").show();
$("#status").html("Loading");
}
function place_point(node,index) {
marker = node;
osm_CurrentMarker=marker;
osm_place_point(marker,index);
}
function getMapNodes(url,href){
pre_loading_blink();
loading_intvl=setInterval("loading_blink()",1000);
//map = [];
var url=serverURL+"?kml="+settings.kml+"&range="+settings.range;
if (settings.mask!="") url+="&mask="+settings.mask; // use second KML file to overwrite main KML file settings
//if (settings.map!="") url+="&map="+settings.map;
url+="&map=all";
//if (settings.start!="") url+="&href="+settings.start+"&range="+settings.range;
url+="&href="+href;
requestKml(url,kmlGot);
//requestKml(url+req,kmlGot);
}
/*
*! -----------------------------------------------------------------------------**
*! FILE NAME : extras.js
*! REVISION : 1.0
*! DESCRIPTION: additional funcions for maps, blinking (to be moved somewhere else later)
*! Copyright (C) 2011 Elphel, Inc.
*!
*! -----------------------------------------------------------------------------**
*! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*!
*! It means that the program's users have the four essential freedoms:
*!
*! * The freedom to run the program, for any purpose (freedom 0).
*! * The freedom to study how the program works, and change it to make it do what you wish (freedom 1).
*! Access to the source code is a precondition for this.
*! * The freedom to redistribute copies so you can help your neighbor (freedom 2).
*! * The freedom to distribute copies of your modified versions to others (freedom 3).
*!
*! By doing this you can give the whole community a chance to benefit from your changes.
*! Access to the source code is a precondition for this.
*! -----------------------------------------------------------------------------**
*/
var osm_CurrentMarker;
function initialize_maps() {
// why did I use range here?
var url=serverURL+"?kml="+settings.kml+"&range="+settings.range;
//var url=serverURL+"?kml="+settings.kml;
if (settings.mask!="") url+="&mask="+settings.mask; // use second KML file to overwrite main KML file settings
//if (settings.map!="") url+="&map="+settings.map;
url+="&map=all";
//if (settings.start!="") url+="&href="+settings.start+"&range="+settings.range;
if (settings.start!="") url+="&href="+settings.start;
if ((typeof(settings.proto)!="undefined") && (settings.proto!="")) url+="&proto="+settings.proto; // use this KML file as a prototype for kml= (copy to kml if kml does not exist)
$("#map_header").trigger('click');
$("#osmap_header").trigger('click');
requestKml(url,place_points);
//requestKml(serverURL+"?kml="+settings.kml,place_points);
/*toggle_gmap();
toggle_osmap(); */
}
function initialize_maps_nowebgl() {
var url=serverURL+"?kml="+settings.kml+"&range="+settings.range;
if (settings.mask!="") url+="&mask="+settings.mask; // use second KML file to overwrite main KML file settings
//if (settings.map!="") url+="&map="+settings.map;
url+="&map=all";
//if (settings.start!="") url+="&href="+settings.start+"&range="+settings.range;
if (settings.start!="") url+="&href="+settings.start;
if ((typeof(settings.proto)!="undefined") && (settings.proto!="")) url+="&proto="+settings.proto; // use this KML file as a prototype for kml= (copy to kml if kml does not exist)
$("#map_header").trigger('click');
$("#osmap_header").trigger('click');
requestKml(url,place_points_nowebgl);
//requestKml(serverURL+"?kml="+settings.kml,place_points);
/*toggle_gmap();
toggle_osmap(); */
}
function loading_blink(){
var d = new Date();
var curr_sec = d.getSeconds();
if (curr_sec%4==1) {
document.getElementById('status').style.color = "white";
document.getElementById('status').innerHTML = "Loading.";
}
else if (curr_sec%4==2) {
document.getElementById('status').style.color = "black";
document.getElementById('status').innerHTML = "Loading..";
}
else if (curr_sec%4==3) {
document.getElementById('status').style.color = "white";
document.getElementById('status').innerHTML = "Loading...";
}
else {
document.getElementById('status').style.color = "black";
document.getElementById('status').innerHTML = "Loading";
}
}
function pre_loading_blink() {
var top = window.innerHeight;
var left = window.innerWidth;
top = top/2;
left = left/2;
document.getElementById('status').style.top = top - $('#status').height()/2;
document.getElementById('status').style.left = left - $('#status').width()/2;
$("#status").show();
$("#status").html("Loading");
}
function place_point(node,index) {
marker = node;
gm_CurrentMarker=marker;
gm_place_point(marker,index);
osm_CurrentMarker=marker;
osm_place_point(marker,index);
}
function getMapNodes(url,href){
pre_loading_blink();
loading_intvl=setInterval("loading_blink()",1000);
//map = [];
var url=serverURL+"?kml="+settings.kml+"&range="+settings.range;
if (settings.mask!="") url+="&mask="+settings.mask; // use second KML file to overwrite main KML file settings
//if (settings.map!="") url+="&map="+settings.map;
url+="&map=all";
//if (settings.start!="") url+="&href="+settings.start+"&range="+settings.range;
url+="&href="+href;
requestKml(url,kmlGot);
//requestKml(url+req,kmlGot);
}
/*!***************************************************************************
*! FILE NAME : g_map.js
*! DESCRIPTION: functions for Google Map API
*! Copyright (C) 2011 Elphel, Inc
*! -----------------------------------------------------------------------------**
*!
*! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------**
*!
*! $Log: g_map.js,v $
*!
*/
var icon_dot;
var icon_dot_blue;
var icon_eyesis;
var gm_points = new Array();
function gm_init_vars(){
icon_dot = new GIcon();
icon_dot.image = "files/map_icons/small_dot.png";
icon_dot.iconSize = new GSize(12, 12);
icon_dot.iconAnchor = new GPoint(6, 6);
icon_dot_blue = new GIcon();
icon_dot_blue.image = "files/map_icons/small_dot_blue.png";
icon_dot_blue.iconSize = new GSize(12, 12);
icon_dot_blue.iconAnchor = new GPoint(6, 6);
icon_eyesis = new GIcon();
icon_eyesis.image = "files/map_icons/eyesis_icon.png";
icon_eyesis.iconSize = new GSize(28, 40);
icon_eyesis.iconAnchor = new GPoint(14, 40);
icon_eyesis.shadow = "files/map_icons/eyesis_shadow.png";
icon_eyesis.shadowSize = new GSize(50, 40);
}
function gm_place_point(mark,n) {
if (n==0) {
gmap.setCenter(new GLatLng(mark.latitude,mark.longitude), zoom);
}
if (n==0) var icon = icon_eyesis;
else var icon = icon_dot;
gm_create_marker(mark,icon);
}
function gm_create_marker(mark,icon){
var i = mark.href;
//var i = mark.href.substr(mark.href.lastIndexOf('/')+1);
var point = new GLatLng(mark.latitude, mark.longitude);
gm_points[i] = new GMarker(point,icon);
GEvent.addListener(gm_points[i], "click", function() {
//gm_set_current_position(mark);
//var req = "?kml="+settings.kml+"&href="+mark.href;
getMapNodes(serverURL,mark.href);
});
GEvent.addListener(gm_points[i], "mouseover", function() {
if (mark.href!=gm_CurrentMarker.href) gm_points[i].setImage(icon_dot_blue.image);
});
GEvent.addListener(gm_points[i], "mouseout", function() {
if (mark.href!=gm_CurrentMarker.href) gm_points[i].setImage(icon_dot.image);
});
gmap.addOverlay(gm_points[i]);
}
function gm_set_current_position(mark){
gm_set_icon(gm_CurrentMarker,icon_dot);
gm_set_icon(mark,icon_eyesis);
gm_CurrentMarker = mark;
}
function gm_remove_marker(i){
gmap.removeOverlay(gm_points[i]);
}
function gm_set_icon(mark,icon) {
gm_remove_marker(mark.href);
//gm_remove_marker(mark.href.substr(mark.href.lastIndexOf('/')+1));
gm_create_marker(mark,icon);
}
/*! -----------------------------------------------------------------------------**
*! FILE NAME : get_kml.js
*! DESCRIPTION: Receives and parses local map information
*! Copyright (C) 2011 Elphel, Inc.
*!
*! -----------------------------------------------------------------------------**
**
** this program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
**
*/
var gXML_req;
function requestKml(url,callbacFunc) { // callbacFunc should accept array of panorama parameters as an argument
gXML_req=new XMLHttpRequest();
gXML_req.open("GET", url, true);
gXML_req.onreadystatechange = function() {
if (typeof(gXML_req)=="undefined") return; ///
if (gXML_req.readyState == 4) {
if (((gXML_req.status >= 200) && (gXML_req.status < 300)) || (gXML_req.status ==304) ||
((typeof(gXML_req.status) =='undefined' ) && ((navigator.userAgent.indexOf("Safari")>=0) ||
(navigator.userAgent.indexOf("Konqueror")>=0)))) {
parseKML(gXML_req.responseXML,callbacFunc);
return;
} else {
if (gXML_req.status) {
alert("There was a problem retrieving the XML data:\n" + (gXML_req.status?gXML_req.statusText:"gXML_req.status==0")+
"\nYou may safely ignore this message if you just reloaded this page");
}
}
}
}
gXML_req.send(null);
}
function parseKML(xml,callbacFunc) {
document.debugXML=xml;
var node;
var panos=[];
map_points= new Array();
var pano;
var cameraHeading=55; // get from KML - heading of the camera when "vehicle" is straight North
var aboveGround=2.05; // get from KML - different for car/person
var cameraType="eyesis_backpack"; // pedestrian
var isWritable=true;
if (xml.getElementsByTagName('open').length>0) {
isWritable= (parseInt(xml.getElementsByTagName('open')[0].firstChild.nodeValue)>0);
}
if (xml.getElementsByTagName('ExtendedData').length>0) { // new: added above ground and camera type
var nodeExtendedData=xml.getElementsByTagName('ExtendedData')[0];
if (nodeExtendedData.getElementsByTagName('cameraType').length>0) cameraType= nodeExtendedData.getElementsByTagName('cameraType')[0].firstChild.nodeValue;
if (nodeExtendedData.getElementsByTagName('aboveGround').length>0)aboveGround=parseFloat(nodeExtendedData.getElementsByTagName('aboveGround')[0].firstChild.nodeValue);
}
console.log(" aboveGround="+aboveGround+" cameraType="+cameraType);
if (xml.getElementsByTagName('PhotoOverlay').length>0) {
for (var numNode=0;numNode<xml.getElementsByTagName('PhotoOverlay').length;numNode++) {
node=xml.getElementsByTagName('PhotoOverlay')[numNode];
if (node.getElementsByTagName('Camera').length>0) {
nodeCam=node.getElementsByTagName('Camera')[0];
pano={};
pano.thisnode = numNode;
if (nodeCam.getElementsByTagName('longitude').length>0) pano.longitude=parseFloat(nodeCam.getElementsByTagName('longitude')[0].firstChild.nodeValue);
if (nodeCam.getElementsByTagName('latitude').length>0) pano.latitude= parseFloat(nodeCam.getElementsByTagName('latitude')[0].firstChild.nodeValue);
if (nodeCam.getElementsByTagName('altitude').length>0) pano.altitude= parseFloat(nodeCam.getElementsByTagName('altitude')[0].firstChild.nodeValue);
if (nodeCam.getElementsByTagName('heading').length>0) pano.heading= parseFloat(nodeCam.getElementsByTagName('heading')[0].firstChild.nodeValue);
if (nodeCam.getElementsByTagName('tilt').length>0) pano.tilt= parseFloat(nodeCam.getElementsByTagName('tilt')[0].firstChild.nodeValue);
if (nodeCam.getElementsByTagName('roll').length>0) pano.roll= parseFloat(nodeCam.getElementsByTagName('roll')[0].firstChild.nodeValue);
if (node.getElementsByTagName('Icon').length>0) {
var nodeIcon=node.getElementsByTagName('Icon')[0];
if (nodeIcon.getElementsByTagName('href').length>0) pano.href=nodeIcon.getElementsByTagName('href')[0].firstChild.nodeValue;
}
if (node.getElementsByTagName('name').length>0) pano.name= (parseInt(node.getElementsByTagName('name')[0].firstChild.nodeValue)); // name is map index
if (node.getElementsByTagName('description').length>0) pano.description= node.getElementsByTagName('description')[0].firstChild.nodeValue;
if (node.getElementsByTagName('visibility').length>0) pano.visibility= (parseInt(node.getElementsByTagName('visibility')[0].firstChild.nodeValue)>0);
else pano.visibility=true; // undefined visible
if (node.getElementsByTagName('open').length>0) pano.open= (parseInt(node.getElementsByTagName('open')[0].firstChild.nodeValue)>0);
if (node.getElementsByTagName('TimeStamp').length>0) {
var nodeTimestamp=node.getElementsByTagName('TimeStamp')[0];
if (nodeTimestamp.getElementsByTagName('when').length>0) {
var whenStr=nodeTimestamp.getElementsByTagName('when')[0].firstChild.nodeValue;
var whenArr=whenStr.replace(/[:\-TZ]/ig," ").split(" ");
pano.time= {year: parseInt(whenArr[0]),
month: parseInt(whenArr[1]),
day: parseInt(whenArr[2]),
hour: parseInt(whenArr[3]),
minute: parseInt(whenArr[4]),
second: parseFloat(whenArr[5])};
}
}
// read array of 3d-visibility ranges, will use 'name' as node number
if (node.getElementsByTagName('ExtendedData').length>0) {
var nodeExtendedData=node.getElementsByTagName('ExtendedData')[0];
if (nodeExtendedData.getElementsByTagName('Visibility3d').length>0) {
var nodeVisibility3d=nodeExtendedData.getElementsByTagName('Visibility3d')[0];
pano.v3d=[];
for (var i=0; i<nodeVisibility3d.getElementsByTagName('v3Range').length;i++) {
var nodev3Range=nodeVisibility3d.getElementsByTagName('v3Range')[i];
var range={};
if (nodev3Range.getElementsByTagName('from').length>0) range.from=parseInt(nodev3Range.getElementsByTagName('from')[0].firstChild.nodeValue);
if (nodev3Range.getElementsByTagName('to').length>0) range.to= parseInt(nodev3Range.getElementsByTagName('to')[0].firstChild.nodeValue);
pano.v3d.push(range);
}
}
}
pano.cameraHeading=cameraHeading; // replace with parsing
pano.aboveGround=aboveGround; // replace with parsing
pano.cameraType=cameraType; // replace with parsing
/*
var debugstr="open: "+pano.open+"\n";
if (typeof(pano.v3d)!='undefined') for (var i=0;i<pano.v3d.length;i++) {
debugstr+="v3d["+i+"]:\n from:"+pano.v3d[i].from+"\n to:"+pano.v3d[i].to+"\n";
}
alert (debugstr);
*/
/* alert ("name="+ pano.name+"\n"+
"description="+ pano.description+"\n"+
"visibility="+ pano.visibility+"\n"+
"cameraHeading="+ pano.cameraHeading+"\n"+
"aboveGround="+ pano.aboveGround+"\n"+
"cameraType="+ pano.cameraType);
*/
// temporary, get from KML later
// alert ("pano data="+pano.toString());
panos.push(pano);
map_points.push(pano);
}
}
}
callbacFunc(panos,isWritable);
}
/*
<TimeStamp>
<when>2011-04-22T17:06:08.466930Z</when>
</TimeStamp>
*/
\ No newline at end of file
// augment Sylvester some
Matrix.Translation = function (v)
{
if (v.elements.length == 2) {
var r = Matrix.I(3);
r.elements[2][0] = v.elements[0];
r.elements[2][1] = v.elements[1];
return r;
}
if (v.elements.length == 3) {
var r = Matrix.I(4);
r.elements[0][3] = v.elements[0];
r.elements[1][3] = v.elements[1];
r.elements[2][3] = v.elements[2];
return r;
}
throw "Invalid length for Translation";
}
Matrix.prototype.flatten = function ()
{
var result = [];
if (this.elements.length == 0)
return [];
for (var j = 0; j < this.elements[0].length; j++)
for (var i = 0; i < this.elements.length; i++)
result.push(this.elements[i][j]);
return result;
}
Matrix.prototype.ensure4x4 = function()
{
if (this.elements.length == 4 &&
this.elements[0].length == 4)
return this;
if (this.elements.length > 4 ||
this.elements[0].length > 4)
return null;
for (var i = 0; i < this.elements.length; i++) {
for (var j = this.elements[i].length; j < 4; j++) {
if (i == j)
this.elements[i].push(1);
else
this.elements[i].push(0);
}
}
for (var i = this.elements.length; i < 4; i++) {
if (i == 0)
this.elements.push([1, 0, 0, 0]);
else if (i == 1)
this.elements.push([0, 1, 0, 0]);
else if (i == 2)
this.elements.push([0, 0, 1, 0]);
else if (i == 3)
this.elements.push([0, 0, 0, 1]);
}
return this;
};
Matrix.prototype.make3x3 = function()
{
if (this.elements.length != 4 ||
this.elements[0].length != 4)
return null;
return Matrix.create([[this.elements[0][0], this.elements[0][1], this.elements[0][2]],
[this.elements[1][0], this.elements[1][1], this.elements[1][2]],
[this.elements[2][0], this.elements[2][1], this.elements[2][2]]]);
};
Vector.prototype.flatten = function ()
{
return this.elements;
};
function mht(m) {
var s = "";
if (m.length == 16) {
for (var i = 0; i < 4; i++) {
s += "<span style='font-family: monospace'>[" + m[i*4+0].toFixed(4) + "," + m[i*4+1].toFixed(4) + "," + m[i*4+2].toFixed(4) + "," + m[i*4+3].toFixed(4) + "]</span><br>";
}
} else if (m.length == 9) {
for (var i = 0; i < 3; i++) {
s += "<span style='font-family: monospace'>[" + m[i*3+0].toFixed(4) + "," + m[i*3+1].toFixed(4) + "," + m[i*3+2].toFixed(4) + "]</font><br>";
}
} else {
return m.toString();
}
return s;
}
//
// gluLookAt
//
function makeLookAt(ex, ey, ez,
cx, cy, cz,
ux, uy, uz)
{
var eye = $V([ex, ey, ez]);
var center = $V([cx, cy, cz]);
var up = $V([ux, uy, uz]);
var mag;
var z = eye.subtract(center).toUnitVector();
var x = up.cross(z).toUnitVector();
var y = z.cross(x).toUnitVector();
var m = $M([[x.e(1), x.e(2), x.e(3), 0],
[y.e(1), y.e(2), y.e(3), 0],
[z.e(1), z.e(2), z.e(3), 0],
[0, 0, 0, 1]]);
var t = $M([[1, 0, 0, -ex],
[0, 1, 0, -ey],
[0, 0, 1, -ez],
[0, 0, 0, 1]]);
return m.x(t);
}
//
// gluPerspective
//
function makePerspective(fovy, aspect, znear, zfar)
{
var ymax = znear * Math.tan(fovy * Math.PI / 360.0);
var ymin = -ymax;
var xmin = ymin * aspect;
var xmax = ymax * aspect;
return makeFrustum(xmin, xmax, ymin, ymax, znear, zfar);
}
//
// glFrustum
//
function makeFrustum(left, right,
bottom, top,
znear, zfar)
{
var X = 2*znear/(right-left);
var Y = 2*znear/(top-bottom);
var A = (right+left)/(right-left);
var B = (top+bottom)/(top-bottom);
var C = -(zfar+znear)/(zfar-znear);
var D = -2*zfar*znear/(zfar-znear);
return $M([[X, 0, A, 0],
[0, Y, B, 0],
[0, 0, C, D],
[0, 0, -1, 0]]);
}
//
// glOrtho
//
function makeOrtho(left, right, bottom, top, znear, zfar)
{
var tx = - (right + left) / (right - left);
var ty = - (top + bottom) / (top - bottom);
var tz = - (zfar + znear) / (zfar - znear);
return $M([[2 / (right - left), 0, 0, tx],
[0, 2 / (top - bottom), 0, ty],
[0, 0, -2 / (zfar - znear), tz],
[0, 0, 0, 1]]);
}
/*! jQuery v1.6.4 http://jquery.com/ | http://jquery.org/license */
(function(a,b){function cu(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cr(a){if(!cg[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ch||(ch=c.createElement("iframe"),ch.frameBorder=ch.width=ch.height=0),b.appendChild(ch);if(!ci||!ch.createElement)ci=(ch.contentWindow||ch.contentDocument).document,ci.write((c.compatMode==="CSS1Compat"?"<!doctype html>":"")+"<html><body>"),ci.close();d=ci.createElement(a),ci.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ch)}cg[a]=e}return cg[a]}function cq(a,b){var c={};f.each(cm.concat.apply([],cm.slice(0,b)),function(){c[this]=a});return c}function cp(){cn=b}function co(){setTimeout(cp,0);return cn=f.now()}function cf(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ce(){try{return new a.XMLHttpRequest}catch(b){}}function b$(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function bZ(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function bY(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bA.test(a)?d(a,e):bY(a+"["+(typeof e=="object"||f.isArray(e)?b:"")+"]",e,c,d)});else if(!c&&b!=null&&typeof b=="object")for(var e in b)bY(a+"["+e+"]",b[e],c,d);else d(a,b)}function bX(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function bW(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bP,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=bW(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=bW(a,c,d,e,"*",g));return l}function bV(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bL),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function by(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?bt:bu;if(d>0){c!=="border"&&f.each(e,function(){c||(d-=parseFloat(f.css(a,"padding"+this))||0),c==="margin"?d+=parseFloat(f.css(a,c+this))||0:d-=parseFloat(f.css(a,"border"+this+"Width"))||0});return d+"px"}d=bv(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0,c&&f.each(e,function(){d+=parseFloat(f.css(a,"padding"+this))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+this+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+this))||0)});return d+"px"}function bl(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bd,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bk(a){f.nodeName(a,"input")?bj(a):"getElementsByTagName"in a&&f.grep(a.getElementsByTagName("input"),bj)}function bj(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bi(a){return"getElementsByTagName"in a?a.getElementsByTagName("*"):"querySelectorAll"in a?a.querySelectorAll("*"):[]}function bh(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bg(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c=f.expando,d=f.data(a),e=f.data(b,d);if(d=d[c]){var g=d.events;e=e[c]=f.extend({},d);if(g){delete e.handle,e.events={};for(var h in g)for(var i=0,j=g[h].length;i<j;i++)f.event.add(b,h+(g[h][i].namespace?".":"")+g[h][i].namespace,g[h][i],g[h][i].data)}}}}function bf(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function V(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(Q.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function U(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function M(a,b){return(a&&a!=="*"?a+".":"")+b.replace(y,"`").replace(z,"&")}function L(a){var b,c,d,e,g,h,i,j,k,l,m,n,o,p=[],q=[],r=f._data(this,"events");if(!(a.liveFired===this||!r||!r.live||a.target.disabled||a.button&&a.type==="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var s=r.live.slice(0);for(i=0;i<s.length;i++)g=s[i],g.origType.replace(w,"")===a.type?q.push(g.selector):s.splice(i--,1);e=f(a.target).closest(q,a.currentTarget);for(j=0,k=e.length;j<k;j++){m=e[j];for(i=0;i<s.length;i++){g=s[i];if(m.selector===g.selector&&(!n||n.test(g.namespace))&&!m.elem.disabled){h=m.elem,d=null;if(g.preType==="mouseenter"||g.preType==="mouseleave")a.type=g.preType,d=f(a.relatedTarget).closest(g.selector)[0],d&&f.contains(h,d)&&(d=h);(!d||d!==h)&&p.push({elem:h,handleObj:g,level:m.level})}}}for(j=0,k=p.length;j<k;j++){e=p[j];if(c&&e.level>c)break;a.currentTarget=e.elem,a.data=e.handleObj.data,a.handleObj=e.handleObj,o=e.handleObj.origHandler.apply(e.elem,arguments);if(o===!1||a.isPropagationStopped()){c=e.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function J(a,c,d){var e=f.extend({},d[0]);e.type=a,e.originalEvent={},e.liveFired=b,f.event.handle.call(c,e),e.isDefaultPrevented()&&d[0].preventDefault()}function D(){return!0}function C(){return!1}function m(a,c,d){var e=c+"defer",g=c+"queue",h=c+"mark",i=f.data(a,e,b,!0);i&&(d==="queue"||!f.data(a,g,b,!0))&&(d==="mark"||!f.data(a,h,b,!0))&&setTimeout(function(){!f.data(a,g,b,!0)&&!f.data(a,h,b,!0)&&(f.removeData(a,e,!0),i.resolve())},0)}function l(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function k(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(j,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNaN(d)?i.test(d)?f.parseJSON(d):d:parseFloat(d)}catch(g){}f.data(a,c,d)}else d=b}return d}var c=a.document,d=a.navigator,e=a.location,f=function(){function K(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(K,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/\d/,n=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,o=/^[\],:{}\s]*$/,p=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,q=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,r=/(?:^|:|,)(?:\s*\[)+/g,s=/(webkit)[ \/]([\w.]+)/,t=/(opera)(?:.*version)?[ \/]([\w.]+)/,u=/(msie) ([\w.]+)/,v=/(mozilla)(?:.*? rv:([\w.]+))?/,w=/-([a-z]|[0-9])/ig,x=/^-ms-/,y=function(a,b){return(b+"").toUpperCase()},z=d.userAgent,A,B,C,D=Object.prototype.toString,E=Object.prototype.hasOwnProperty,F=Array.prototype.push,G=Array.prototype.slice,H=String.prototype.trim,I=Array.prototype.indexOf,J={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=n.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.6.4",length:0,size:function(){return this.length},toArray:function(){return G.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?F.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),B.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(G.apply(this,arguments),"slice",G.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:F,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;B.resolveWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!B){B=e._Deferred();if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",C,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",C),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&K()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNaN:function(a){return a==null||!m.test(a)||isNaN(a)},type:function(a){return a==null?String(a):J[D.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!E.call(a,"constructor")&&!E.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||E.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(o.test(b.replace(p,"@").replace(q,"]").replace(r,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(x,"ms-").replace(w,y)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:H?function(a){return a==null?"":H.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?F.call(c,a):e.merge(c,a)}return c},inArray:function(a,b){if(!b)return-1;if(I)return I.call(b,a);for(var c=0,d=b.length;c<d;c++)if(b[c]===a)return c;return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=G.call(arguments,2),g=function(){return a.apply(c,f.concat(G.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h){var i=a.length;if(typeof c=="object"){for(var j in c)e.access(a,j,c[j],f,g,d);return a}if(d!==b){f=!h&&f&&e.isFunction(d);for(var k=0;k<i;k++)g(a[k],c,f?d.call(a[k],k,g(a[k],c)):d,h);return a}return i?g(a[0],c):b},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=s.exec(a)||t.exec(a)||u.exec(a)||a.indexOf("compatible")<0&&v.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){J["[object "+b+"]"]=b.toLowerCase()}),A=e.uaMatch(z),A.browser&&(e.browser[A.browser]=!0,e.browser.version=A.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?C=function(){c.removeEventListener("DOMContentLoaded",C,!1),e.ready()}:c.attachEvent&&(C=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",C),e.ready())});return e}(),g="done fail isResolved isRejected promise then always pipe".split(" "),h=[].slice;f.extend({_Deferred:function(){var a=[],b,c,d,e={done:function(){if(!d){var c=arguments,g,h,i,j,k;b&&(k=b,b=0);for(g=0,h=c.length;g<h;g++)i=c[g],j=f.type(i),j==="array"?e.done.apply(e,i):j==="function"&&a.push(i);k&&e.resolveWith(k[0],k[1])}return this},resolveWith:function(e,f){if(!d&&!b&&!c){f=f||[],c=1;try{while(a[0])a.shift().apply(e,f)}finally{b=[e,f],c=0}}return this},resolve:function(){e.resolveWith(this,arguments);return this},isResolved:function(){return!!c||!!b},cancel:function(){d=1,a=[];return this}};return e},Deferred:function(a){var b=f._Deferred(),c=f._Deferred(),d;f.extend(b,{then:function(a,c){b.done(a).fail(c);return this},always:function(){return b.done.apply(b,arguments).fail.apply(this,arguments)},fail:c.done,rejectWith:c.resolveWith,reject:c.resolve,isRejected:c.isResolved,pipe:function(a,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[c,"reject"]},function(a,c){var e=c[0],g=c[1],h;f.isFunction(e)?b[a](function(){h=e.apply(this,arguments),h&&f.isFunction(h.promise)?h.promise().then(d.resolve,d.reject):d[g+"With"](this===b?d:this,[h])}):b[a](d[g])})}).promise()},promise:function(a){if(a==null){if(d)return d;d=a={}}var c=g.length;while(c--)a[g[c]]=b[g[c]];return a}}),b.done(c.cancel).fail(b.cancel),delete b.cancel,a&&a.call(b,b);return b},when:function(a){function i(a){return function(c){b[a]=arguments.length>1?h.call(arguments,0):c,--e||g.resolveWith(g,h.call(b,0))}}var b=arguments,c=0,d=b.length,e=d,g=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred();if(d>1){for(;c<d;c++)b[c]&&f.isFunction(b[c].promise)?b[c].promise().then(i(c),g.reject):--e;e||g.resolveWith(g,b)}else g!==a&&g.resolveWith(g,d?[a]:[]);return g.promise()}}),f.support=function(){var a=c.createElement("div"),b=c.documentElement,d,e,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u;a.setAttribute("className","t"),a.innerHTML=" <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=a.getElementsByTagName("*"),e=a.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=a.getElementsByTagName("input")[0],k={leadingWhitespace:a.firstChild.nodeType===3,tbody:!a.getElementsByTagName("tbody").length,htmlSerialize:!!a.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55$/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:a.className!=="t",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,k.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,k.optDisabled=!h.disabled;try{delete a.test}catch(v){k.deleteExpando=!1}!a.addEventListener&&a.attachEvent&&a.fireEvent&&(a.attachEvent("onclick",function(){k.noCloneEvent=!1}),a.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),k.radioValue=i.value==="t",i.setAttribute("checked","checked"),a.appendChild(i),l=c.createDocumentFragment(),l.appendChild(a.firstChild),k.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,a.innerHTML="",a.style.width=a.style.paddingLeft="1px",m=c.getElementsByTagName("body")[0],o=c.createElement(m?"div":"body"),p={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},m&&f.extend(p,{position:"absolute",left:"-1000px",top:"-1000px"});for(t in p)o.style[t]=p[t];o.appendChild(a),n=m||b,n.insertBefore(o,n.firstChild),k.appendChecked=i.checked,k.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,k.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="<div style='width:4px;'></div>",k.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>",q=a.getElementsByTagName("td"),u=q[0].offsetHeight===0,q[0].style.display="",q[1].style.display="none",k.reliableHiddenOffsets=u&&q[0].offsetHeight===0,a.innerHTML="",c.defaultView&&c.defaultView.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",a.appendChild(j),k.reliableMarginRight=(parseInt((c.defaultView.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0),o.innerHTML="",n.removeChild(o);if(a.attachEvent)for(t in{submit:1,change:1,focusin:1})s="on"+t,u=s in a,u||(a.setAttribute(s,"return;"),u=typeof a[s]=="function"),k[t+"Bubbles"]=u;o=l=g=h=m=j=a=i=null;return k}(),f.boxModel=f.support.boxModel;var i=/^(?:\{.*\}|\[.*\])$/,j=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!l(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i=f.expando,j=typeof c=="string",k=a.nodeType,l=k?f.cache:a,m=k?a[f.expando]:a[f.expando]&&f.expando;if((!m||e&&m&&l[m]&&!l[m][i])&&j&&d===b)return;m||(k?a[f.expando]=m=++f.uuid:m=f.expando),l[m]||(l[m]={},k||(l[m].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?l[m][i]=f.extend(l[m][i],c):l[m]=f.extend(l[m],c);g=l[m],e&&(g[i]||(g[i]={}),g=g[i]),d!==b&&(g[f.camelCase(c)]=d);if(c==="events"&&!g[c])return g[i]&&g[i].events;j?(h=g[c],h==null&&(h=g[f.camelCase(c)])):h=g;return h}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e=f.expando,g=a.nodeType,h=g?f.cache:a,i=g?a[f.expando]:f.expando;if(!h[i])return;if(b){d=c?h[i][e]:h[i];if(d){d[b]||(b=f.camelCase(b)),delete d[b];if(!l(d))return}}if(c){delete h[i][e];if(!l(h[i]))return}var j=h[i][e];f.support.deleteExpando||!h.setInterval?delete h[i]:h[i]=null,j?(h[i]={},g||(h[i].toJSON=f.noop),h[i][e]=j):g&&(f.support.deleteExpando?delete a[f.expando]:a.removeAttribute?a.removeAttribute(f.expando):a[f.expando]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d=null;if(typeof a=="undefined"){if(this.length){d=f.data(this[0]);if(this[0].nodeType===1){var e=this[0].attributes,g;for(var h=0,i=e.length;h<i;h++)g=e[h].name,g.indexOf("data-")===0&&(g=f.camelCase(g.substring(5)),k(this[0],g,d[g]))}}return d}if(typeof a=="object")return this.each(function(){f.data(this,a)});var j=a.split(".");j[1]=j[1]?"."+j[1]:"";if(c===b){d=this.triggerHandler("getData"+j[1]+"!",[j[0]]),d===b&&this.length&&(d=f.data(this[0],a),d=k(this[0],a,d));return d===b&&j[1]?this.data(j[0]):d}return this.each(function(){var b=f(this),d=[j[0],c];b.triggerHandler("setData"+j[1]+"!",d),f.data(this,a,c),b.triggerHandler("changeData"+j[1]+"!",d)})},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,c){a&&(c=(c||"fx")+"mark",f.data(a,c,(f.data(a,c,b,!0)||0)+1,!0))},_unmark:function(a,c,d){a!==!0&&(d=c,c=a,a=!1);if(c){d=d||"fx";var e=d+"mark",g=a?0:(f.data(c,e,b,!0)||1)-1;g?f.data(c,e,g,!0):(f.removeData(c,e,!0),m(c,d,"mark"))}},queue:function(a,c,d){if(a){c=(c||"fx")+"queue";var e=f.data(a,c,b,!0);d&&(!e||f.isArray(d)?e=f.data(a,c,f.makeArray(d),!0):e.push(d));return e||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e;d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),d.call(a,function(){f.dequeue(a,b)})),c.length||(f.removeData(a,b+"queue",!0),m(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){typeof a!="string"&&(c=a,a="fx");if(c===b)return f.queue(this[0],a);return this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(){var c=this;setTimeout(function(){f.dequeue(c,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f._Deferred(),!0))h++,l.done(m);m();return d.promise()}});var n=/[\n\t\r]/g,o=/\s+/,p=/\r/g,q=/^(?:button|input)$/i,r=/^(?:button|input|object|select|textarea)$/i,s=/^a(?:rea)?$/i,t=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,u,v;f.fn.extend({attr:function(a,b){return f.access(this,a,b,!0,f.attr)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,a,b,!0,f.prop)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(o);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(o);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(n," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(o);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ";for(var c=0,d=this.length;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(n," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e=this[0];if(!arguments.length){if(e){c=f.valHooks[e.nodeName.toLowerCase()]||f.valHooks[e.type];if(c&&"get"in c&&(d=c.get(e,"value"))!==b)return d;d=e.value;return typeof d=="string"?d.replace(p,""):d==null?"":d}return b}var g=f.isFunction(a);return this.each(function(d){var e=f(this),h;if(this.nodeType===1){g?h=a.call(this,d,e.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c=a.selectedIndex,d=[],e=a.options,g=a.type==="select-one";if(c<0)return null;for(var h=g?c:0,i=g?c+1:e.length;h<i;h++){var j=e[h];if(j.selected&&(f.support.optDisabled?!j.disabled:j.getAttribute("disabled")===null)&&(!j.parentNode.disabled||!f.nodeName(j.parentNode,"optgroup"))){b=f(j).val();if(g)return b;d.push(b)}}if(g&&!d.length&&e.length)return f(e[c]).val();return d},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attrFix:{tabindex:"tabIndex"},attr:function(a,c,d,e){var g=a.nodeType;if(!a||g===3||g===8||g===2)return b;if(e&&c in f.attrFn)return f(a)[c](d);if(!("getAttribute"in a))return f.prop(a,c,d);var h,i,j=g!==1||!f.isXMLDoc(a);j&&(c=f.attrFix[c]||c,i=f.attrHooks[c],i||(t.test(c)?i=v:u&&(i=u)));if(d!==b){if(d===null){f.removeAttr(a,c);return b}if(i&&"set"in i&&j&&(h=i.set(a,d,c))!==b)return h;a.setAttribute(c,""+d);return d}if(i&&"get"in i&&j&&(h=i.get(a,c))!==null)return h;h=a.getAttribute(c);return h===null?b:h},removeAttr:function(a,b){var c;a.nodeType===1&&(b=f.attrFix[b]||b,f.attr(a,b,""),a.removeAttribute(b),t.test(b)&&(c=f.propFix[b]||b)in a&&(a[c]=!1))},attrHooks:{type:{set:function(a,b){if(q.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(u&&f.nodeName(a,"button"))return u.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(u&&f.nodeName(a,"button"))return u.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e=a.nodeType;if(!a||e===3||e===8||e===2)return b;var g,h,i=e!==1||!f.isXMLDoc(a);i&&(c=f.propFix[c]||c,h=f.propHooks[c]);return d!==b?h&&"set"in h&&(g=h.set(a,d,c))!==b?g:a[c]=d:h&&"get"in h&&(g=h.get(a,c))!==null?g:a[c]},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):r.test(a.nodeName)||s.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabIndex=f.propHooks.tabIndex,v={get:function(a,c){var d;return f.prop(a,c)===!0||(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},f.support.getSetAttribute||(u=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&d.nodeValue!==""?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})})),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var w=/\.(.*)$/,x=/^(?:textarea|input|select)$/i,y=/\./g,z=/ /g,A=/[^\w\s.|`]/g,B=function(a){return a.replace(A,"\\$&")};f.event={add:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){if(d===!1)d=C;else if(!d)return;var g,h;d.handler&&(g=d,d=g.handler),d.guid||(d.guid=f.guid++);var i=f._data(a);if(!i)return;var j=i.events,k=i.handle;j||(i.events=j={}),k||(i.handle=k=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.handle.apply(k.elem,arguments):b}),k.elem=a,c=c.split(" ");var l,m=0,n;while(l=c[m++]){h=g?f.extend({},g):{handler:d,data:e},l.indexOf(".")>-1?(n=l.split("."),l=n.shift(),h.namespace=n.slice(0).sort().join(".")):(n=[],h.namespace=""),h.type=l,h.guid||(h.guid=d.guid);var o=j[l],p=f.event.special[l]||{};if(!o){o=j[l]=[];if(!p.setup||p.setup.call(a,e,n,k)===!1)a.addEventListener?a.addEventListener(l,k,!1):a.attachEvent&&a.attachEvent("on"+l,k)}p.add&&(p.add.call(a,h),h.handler.guid||(h.handler.guid=d.guid)),o.push(h),f.event.global[l]=!0}a=null}},global:{},remove:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){d===!1&&(d=C);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=f.hasData(a)&&f._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(d=c.handler,c=c.type);if(!c||typeof c=="string"&&c.charAt(0)==="."){c=c||"";for(h in t)f.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+f.map(m.slice(0).sort(),B).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!d){for(j=0;j<p.length;j++){q=p[j];if(l||n.test(q.namespace))f.event.remove(a,r,q.handler,j),p.splice(j--,1)}continue}o=f.event.special[h]||{};for(j=e||0;j<p.length;j++){q=p[j];if(d.guid===q.guid){if(l||n.test(q.namespace))e==null&&p.splice(j--,1),o.remove&&o.remove.call(a,q);if(e!=null)break}}if(p.length===0||e!=null&&p.length===1)(!o.teardown||o.teardown.call(a,m)===!1)&&f.removeEvent(a,h,s.handle),g=null,delete
t[h]}if(f.isEmptyObject(t)){var u=s.handle;u&&(u.elem=null),delete s.events,delete s.handle,f.isEmptyObject(s)&&f.removeData(a,b,!0)}}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){var h=c.type||c,i=[],j;h.indexOf("!")>=0&&(h=h.slice(0,-1),j=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if(!!e&&!f.event.customEvent[h]||!!f.event.global[h]){c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.exclusive=j,c.namespace=i.join("."),c.namespace_re=new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)");if(g||!e)c.preventDefault(),c.stopPropagation();if(!e){f.each(f.cache,function(){var a=f.expando,b=this[a];b&&b.events&&b.events[h]&&f.event.trigger(c,d,b.handle.elem)});return}if(e.nodeType===3||e.nodeType===8)return;c.result=b,c.target=e,d=d!=null?f.makeArray(d):[],d.unshift(c);var k=e,l=h.indexOf(":")<0?"on"+h:"";do{var m=f._data(k,"handle");c.currentTarget=k,m&&m.apply(k,d),l&&f.acceptData(k)&&k[l]&&k[l].apply(k,d)===!1&&(c.result=!1,c.preventDefault()),k=k.parentNode||k.ownerDocument||k===c.target.ownerDocument&&a}while(k&&!c.isPropagationStopped());if(!c.isDefaultPrevented()){var n,o=f.event.special[h]||{};if((!o._default||o._default.call(e.ownerDocument,c)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)){try{l&&e[h]&&(n=e[l],n&&(e[l]=null),f.event.triggered=h,e[h]())}catch(p){}n&&(e[l]=n),f.event.triggered=b}}return c.result}},handle:function(c){c=f.event.fix(c||a.event);var d=((f._data(this,"events")||{})[c.type]||[]).slice(0),e=!c.exclusive&&!c.namespace,g=Array.prototype.slice.call(arguments,0);g[0]=c,c.currentTarget=this;for(var h=0,i=d.length;h<i;h++){var j=d[h];if(e||c.namespace_re.test(j.namespace)){c.handler=j.handler,c.data=j.data,c.handleObj=j;var k=j.handler.apply(this,g);k!==b&&(c.result=k,k===!1&&(c.preventDefault(),c.stopPropagation()));if(c.isImmediatePropagationStopped())break}}return c.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(a){if(a[f.expando])return a;var d=a;a=f.Event(d);for(var e=this.props.length,g;e;)g=this.props[--e],a[g]=d[g];a.target||(a.target=a.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),!a.relatedTarget&&a.fromElement&&(a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement);if(a.pageX==null&&a.clientX!=null){var h=a.target.ownerDocument||c,i=h.documentElement,j=h.body;a.pageX=a.clientX+(i&&i.scrollLeft||j&&j.scrollLeft||0)-(i&&i.clientLeft||j&&j.clientLeft||0),a.pageY=a.clientY+(i&&i.scrollTop||j&&j.scrollTop||0)-(i&&i.clientTop||j&&j.clientTop||0)}a.which==null&&(a.charCode!=null||a.keyCode!=null)&&(a.which=a.charCode!=null?a.charCode:a.keyCode),!a.metaKey&&a.ctrlKey&&(a.metaKey=a.ctrlKey),!a.which&&a.button!==b&&(a.which=a.button&1?1:a.button&2?3:a.button&4?2:0);return a},guid:1e8,proxy:f.proxy,special:{ready:{setup:f.bindReady,teardown:f.noop},live:{add:function(a){f.event.add(this,M(a.origType,a.selector),f.extend({},a,{handler:L,guid:a.handler.guid}))},remove:function(a){f.event.remove(this,M(a.origType,a.selector),a)}},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}}},f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!this.preventDefault)return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?D:C):this.type=a,b&&f.extend(this,b),this.timeStamp=f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=D;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=D;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=D,this.stopPropagation()},isDefaultPrevented:C,isPropagationStopped:C,isImmediatePropagationStopped:C};var E=function(a){var b=a.relatedTarget,c=!1,d=a.type;a.type=a.data,b!==this&&(b&&(c=f.contains(this,b)),c||(f.event.handle.apply(this,arguments),a.type=d))},F=function(a){a.type=a.data,f.event.handle.apply(this,arguments)};f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={setup:function(c){f.event.add(this,b,c&&c.selector?F:E,a)},teardown:function(a){f.event.remove(this,b,a&&a.selector?F:E)}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(a,b){if(!f.nodeName(this,"form"))f.event.add(this,"click.specialSubmit",function(a){var b=a.target,c=f.nodeName(b,"input")||f.nodeName(b,"button")?b.type:"";(c==="submit"||c==="image")&&f(b).closest("form").length&&J("submit",this,arguments)}),f.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,c=f.nodeName(b,"input")||f.nodeName(b,"button")?b.type:"";(c==="text"||c==="password")&&f(b).closest("form").length&&a.keyCode===13&&J("submit",this,arguments)});else return!1},teardown:function(a){f.event.remove(this,".specialSubmit")}});if(!f.support.changeBubbles){var G,H=function(a){var b=f.nodeName(a,"input")?a.type:"",c=a.value;b==="radio"||b==="checkbox"?c=a.checked:b==="select-multiple"?c=a.selectedIndex>-1?f.map(a.options,function(a){return a.selected}).join("-"):"":f.nodeName(a,"select")&&(c=a.selectedIndex);return c},I=function(c){var d=c.target,e,g;if(!!x.test(d.nodeName)&&!d.readOnly){e=f._data(d,"_change_data"),g=H(d),(c.type!=="focusout"||d.type!=="radio")&&f._data(d,"_change_data",g);if(e===b||g===e)return;if(e!=null||g)c.type="change",c.liveFired=b,f.event.trigger(c,arguments[1],d)}};f.event.special.change={filters:{focusout:I,beforedeactivate:I,click:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(c==="radio"||c==="checkbox"||f.nodeName(b,"select"))&&I.call(this,a)},keydown:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(a.keyCode===13&&!f.nodeName(b,"textarea")||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&I.call(this,a)},beforeactivate:function(a){var b=a.target;f._data(b,"_change_data",H(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in G)f.event.add(this,c+".specialChange",G[c]);return x.test(this.nodeName)},teardown:function(a){f.event.remove(this,".specialChange");return x.test(this.nodeName)}},G=f.event.special.change.filters,G.focus=G.beforeactivate}f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){function e(a){var c=f.event.fix(a);c.type=b,c.originalEvent={},f.event.trigger(c,null,c.target),c.isDefaultPrevented()&&a.preventDefault()}var d=0;f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.each(["bind","one"],function(a,c){f.fn[c]=function(a,d,e){var g;if(typeof a=="object"){for(var h in a)this[c](h,d,a[h],e);return this}if(arguments.length===2||d===!1)e=d,d=b;c==="one"?(g=function(a){f(this).unbind(a,g);return e.apply(this,arguments)},g.guid=e.guid||f.guid++):g=e;if(a==="unload"&&c!=="one")this.one(a,d,e);else for(var i=0,j=this.length;i<j;i++)f.event.add(this[i],a,g,d);return this}}),f.fn.extend({unbind:function(a,b){if(typeof a=="object"&&!a.preventDefault)for(var c in a)this.unbind(c,a[c]);else for(var d=0,e=this.length;d<e;d++)f.event.remove(this[d],a,b);return this},delegate:function(a,b,c,d){return this.live(b,c,d,a)},undelegate:function(a,b,c){return arguments.length===0?this.unbind("live"):this.die(b,null,c,a)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f.data(this,"lastToggle"+a.guid)||0)%d;f.data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var K={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};f.each(["live","die"],function(a,c){f.fn[c]=function(a,d,e,g){var h,i=0,j,k,l,m=g||this.selector,n=g?this:f(this.context);if(typeof a=="object"&&!a.preventDefault){for(var o in a)n[c](o,d,a[o],m);return this}if(c==="die"&&!a&&g&&g.charAt(0)==="."){n.unbind(g);return this}if(d===!1||f.isFunction(d))e=d||C,d=b;a=(a||"").split(" ");while((h=a[i++])!=null){j=w.exec(h),k="",j&&(k=j[0],h=h.replace(w,""));if(h==="hover"){a.push("mouseenter"+k,"mouseleave"+k);continue}l=h,K[h]?(a.push(K[h]+k),h=h+k):h=(K[h]||h)+k;if(c==="live")for(var p=0,q=n.length;p<q;p++)f.event.add(n[p],"live."+M(h,m),{data:d,selector:m,handler:e,origType:h,origHandler:e,preType:l});else n.unbind("live."+M(h,m),e)}return this}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.bind(b,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g<h;g++){var i=d[g];if(i){var j=!1;i=i[a];while(i){if(i.sizcache===c){j=d[i.sizset];break}if(i.nodeType===1){f||(i.sizcache=c,i.sizset=g);if(typeof b!="string"){if(i===b){j=!0;break}}else if(k.filter(b,[i]).length>0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g<h;g++){var i=d[g];if(i){var j=!1;i=i[a];while(i){if(i.sizcache===c){j=d[i.sizset];break}i.nodeType===1&&!f&&(i.sizcache=c,i.sizset=g);if(i.nodeName.toLowerCase()===b){j=i;break}i=i[a]}d[g]=j}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d=0,e=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,f,g){f=f||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return f;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(e.call(n)==="[object Array]")if(!u)f.push.apply(f,n);else if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&f.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&f.push(j[t]);else p(n,f);o&&(k(o,h,f,g),k.uniqueSort(f));return f};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},k.matches=function(a,b){return k(a,null,null,b)},k.matchesSelector=function(a,b){return k(b,null,null,[a]).length>0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e<f;e++){var g,h=l.order[e];if(g=l.leftMatch[h].exec(a)){var j=g[1];g.splice(1,1);if(j.substr(j.length-1)!=="\\"){g[1]=(g[1]||"").replace(i,""),d=l.find[h](g,b,c);if(d!=null){a=a.replace(l.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},k.filter=function(a,c,d,e){var f,g,h=a,i=[],j=c,m=c&&c[0]&&k.isXML(c[0]);while(a&&c.length){for(var n in l.filter)if((f=l.leftMatch[n].exec(a))!=null&&f[2]){var o,p,q=l.filter[n],r=f[1];g=!1,f.splice(1,1);if(r.substr(r.length-1)==="\\")continue;j===i&&(i=[]);if(l.preFilter[n]){f=l.preFilter[n](f,j,d,i,e,m);if(!f)g=o=!0;else if(f===!0)continue}if(f)for(var s=0;(p=j[s])!=null;s++)if(p){o=q(p,f,s,j);var t=e^!!o;d&&o!=null?t?g=!0:j[s]=!1:t&&(i.push(p),g=!0)}if(o!==b){d||(j=i),a=a.replace(l.match[n],"");if(!g)return[];break}}if(a===h)if(g==null)k.error(a);else break;h=a}return j},k.error=function(a){throw"Syntax error, unrecognized expression: "+a};var l=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!j.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&k.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&k.filter(b,a,!0)}},"":function(a,b,c){var e,f=d++,g=u;typeof b=="string"&&!j.test(b)&&(b=b.toLowerCase(),e=b,g=t),g("parentNode",b,f,a,e,c)},"~":function(a,b,c){var e,f=d++,g=u;typeof b=="string"&&!j.test(b)&&(b=b.toLowerCase(),e=b,g=t),g("previousSibling",b,f,a,e,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(i,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=d++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}k.error(e)},CHILD:function(a,b){var c=b[1],d=a;switch(c){case"only":case"first":while(d=d.previousSibling)if(d.nodeType===1)return!1;if(c==="first")return!0;d=a;case"last":while(d=d.nextSibling)if(d.nodeType===1)return!1;return!0;case"nth":var e=b[2],f=b[3];if(e===1&&f===0)return!0;var g=b[0],h=a.parentNode;if(h&&(h.sizcache!==g||!a.nodeIndex)){var i=0;for(d=h.firstChild;d;d=d.nextSibling)d.nodeType===1&&(d.nodeIndex=++i);h.sizcache=g}var j=a.nodeIndex-f;return e===0?j===0:j%e===0&&j/e>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(e.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var f=a.length;c<f;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var r,s;c.documentElement.compareDocumentPosition?r=function(a,b){if(a===b){g=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(r=function(a,b){if(a===b){g=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],h=a.parentNode,i=b.parentNode,j=h;if(h===i)return s(a,b);if(!h)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return s(e[k],f[k]);return k===c?s(a,f[k],-1):s(e[k],b,1)},s=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),k.getText=function(a){var b="",c;for(var d=0;a[d];d++)c=a[d],c.nodeType===3||c.nodeType===4?b+=c.nodeValue:c.nodeType!==8&&(b+=k.getText(c.childNodes));return b},function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(e||!l.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return k(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g<h;g++)k(a,f[g],d);return k.filter(e,d)};f.find=k,f.expr=k.selectors,f.expr[":"]=f.expr.filters,f.unique=k.uniqueSort,f.text=k.getText,f.isXMLDoc=k.isXML,f.contains=k.contains}();var N=/Until$/,O=/^(?:parents|prevUntil|prevAll)/,P=/,/,Q=/^.[^:#\[\.,]*$/,R=Array.prototype.slice,S=f.expr.match.POS,T={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(V(this,a,!1),"not",a)},filter:function(a){return this.pushStack(V(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(d=0,e=a.length;d<e;d++)i=a[d],j[i]||(j[i]=S.test(i)?f(i,b||this.context):i);while(g&&g.ownerDocument&&g!==b){for(i in j)h=j[i],(h.jquery?h.index(g)>-1:f(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=S.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(l?l.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(U(c[0])||U(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c),g=R.call(arguments);N.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!T[a]?f.unique(e):e,(this.length>1||P.test(d))&&O.test(a)&&(e=e.reverse());return this.pushStack(e,a,g.join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/<tbody/i,_=/<|&#?\w+;/,ba=/<(?:script|object|embed|option|style)/i,bb=/checked\s*(?:[^=]|=\s*.checked.)/i,bc=/\/(java|ecma)script/i,bd=/^\s*<!(?:\[CDATA\[|\-\-)/,be={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};be.optgroup=be.option,be.tbody=be.tfoot=be.colgroup=be.caption=be.thead,be.th=be.td,f.support.htmlSerialize||(be._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){f(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!be[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1></$2>");try{for(var c=0,d=this.length;c<d;c++)this[c].nodeType===1&&(f.cleanData(this[c].getElementsByTagName("*")),this[c].innerHTML=a)}catch(e){this.empty().append(a)}}else f.isFunction(a)?this.each(function(b){var c=f(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bb.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bf(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,bl)}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i;b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof a[0]=="string"&&a[0].length<512&&i===c&&a[0].charAt(0)==="<"&&!ba.test(a[0])&&(f.support.checkClone||!bb.test(a[0]))&&(g=!0,h=f.fragments[a[0]],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean
(a,i,e,d)),g&&(f.fragments[a[0]]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d=a.cloneNode(!0),e,g,h;if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bh(a,d),e=bi(a),g=bi(d);for(h=0;e[h];++h)g[h]&&bh(e[h],g[h])}if(b){bg(a,d);if(c){e=bi(a),g=bi(d);for(h=0;e[h];++h)bg(e[h],g[h])}}e=g=null;return d},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!_.test(k))k=b.createTextNode(k);else{k=k.replace(Y,"<$1></$2>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=be[l]||be._default,n=m[0],o=b.createElement("div");o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]==="<table>"&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i<r;i++)bk(k[i]);else bk(k);k.nodeType?h.push(k):h=f.merge(h,k)}if(d){g=function(a){return!a.type||bc.test(a.type)};for(j=0;h[j];j++)if(e&&f.nodeName(h[j],"script")&&(!h[j].type||h[j].type.toLowerCase()==="text/javascript"))e.push(h[j].parentNode?h[j].parentNode.removeChild(h[j]):h[j]);else{if(h[j].nodeType===1){var s=f.grep(h[j].getElementsByTagName("script"),g);h.splice.apply(h,[j+1,0].concat(s))}d.appendChild(h[j])}}return h},cleanData:function(a){var b,c,d=f.cache,e=f.expando,g=f.event.special,h=f.support.deleteExpando;for(var i=0,j;(j=a[i])!=null;i++){if(j.nodeName&&f.noData[j.nodeName.toLowerCase()])continue;c=j[f.expando];if(c){b=d[c]&&d[c][e];if(b&&b.events){for(var k in b.events)g[k]?f.event.remove(j,k):f.removeEvent(j,k,b.handle);b.handle&&(b.handle.elem=null)}h?delete j[f.expando]:j.removeAttribute&&j.removeAttribute(f.expando),delete d[c]}}}});var bm=/alpha\([^)]*\)/i,bn=/opacity=([^)]*)/,bo=/([A-Z]|^ms)/g,bp=/^-?\d+(?:px)?$/i,bq=/^-?\d/,br=/^([\-+])=([\-+.\de]+)/,bs={position:"absolute",visibility:"hidden",display:"block"},bt=["Left","Right"],bu=["Top","Bottom"],bv,bw,bx;f.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return f.access(this,a,c,!0,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)})},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bv(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=br.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(bv)return bv(a,c)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]}}),f.curCSS=f.css,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){var e;if(c){if(a.offsetWidth!==0)return by(a,b,d);f.swap(a,bs,function(){e=by(a,b,d)});return e}},set:function(a,b){if(!bp.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bn.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNaN(b)?"":"alpha(opacity="+b*100+")",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bm,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bm.test(g)?g.replace(bm,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bv(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bw=function(a,c){var d,e,g;c=c.replace(bo,"-$1").toLowerCase();if(!(e=a.ownerDocument.defaultView))return b;if(g=e.getComputedStyle(a,null))d=g.getPropertyValue(c),d===""&&!f.contains(a.ownerDocument.documentElement,a)&&(d=f.style(a,c));return d}),c.documentElement.currentStyle&&(bx=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bp.test(d)&&bq.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bv=bw||bx,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bz=/%20/g,bA=/\[\]$/,bB=/\r?\n/g,bC=/#.*$/,bD=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bE=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bF=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bG=/^(?:GET|HEAD)$/,bH=/^\/\//,bI=/\?/,bJ=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bK=/^(?:select|textarea)/i,bL=/\s+/,bM=/([?&])_=[^&]*/,bN=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bO=f.fn.load,bP={},bQ={},bR,bS,bT=["*/"]+["*"];try{bR=e.href}catch(bU){bR=c.createElement("a"),bR.href="",bR=bR.href}bS=bN.exec(bR.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bO)return bO.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bJ,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bK.test(this.nodeName)||bE.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bB,"\r\n")}}):{name:b.name,value:c.replace(bB,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.bind(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?bX(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),bX(a,b);return a},ajaxSettings:{url:bR,isLocal:bF.test(bS[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bT},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bV(bP),ajaxTransport:bV(bQ),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?bZ(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=b$(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.resolveWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f._Deferred(),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bD.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.done,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bC,"").replace(bH,bS[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bL),d.crossDomain==null&&(r=bN.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bS[1]&&r[2]==bS[2]&&(r[3]||(r[1]==="http:"?80:443))==(bS[3]||(bS[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bW(bP,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bG.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bI.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bM,"$1_="+x);d.url=y+(y===d.url?(bI.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bT+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bW(bQ,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){s<2?w(-1,z):f.error(z)}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)bY(g,a[g],c,e);return d.join("&").replace(bz,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var b_=f.now(),ca=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+b_++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ca.test(b.url)||e&&ca.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ca,l),b.url===j&&(e&&(k=k.replace(ca,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cb=a.ActiveXObject?function(){for(var a in cd)cd[a](0,1)}:!1,cc=0,cd;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ce()||cf()}:ce,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cb&&delete cd[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cc,cb&&(cd||(cd={},f(a).unload(cb)),cd[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cg={},ch,ci,cj=/^(?:toggle|show|hide)$/,ck=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cl,cm=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cn;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cq("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),e===""&&f.css(d,"display")==="none"&&f._data(d,"olddisplay",cr(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(cq("hide",3),a,b,c);for(var d=0,e=this.length;d<e;d++)if(this[d].style){var g=f.css(this[d],"display");g!=="none"&&!f._data(this[d],"olddisplay")&&f._data(this[d],"olddisplay",g)}for(d=0;d<e;d++)this[d].style&&(this[d].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(cq("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return this[e.queue===!1?"each":"queue"](function(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]),h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(f.support.inlineBlockNeedsLayout?(j=cr(this.nodeName),j==="inline"?this.style.display="inline-block":(this.style.display="inline",this.style.zoom=1)):this.style.display="inline-block"))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)k=new f.fx(this,b,i),h=a[i],cj.test(h)?k[h==="toggle"?d?"show":"hide":h]():(l=ck.exec(h),m=k.cur(),l?(n=parseFloat(l[2]),o=l[3]||(f.cssNumber[i]?"":"px"),o!=="px"&&(f.style(this,i,(n||1)+o),m=(n||1)/k.cur()*m,f.style(this,i,m+o)),l[1]&&(n=(l[1]==="-="?-1:1)*n+m),k.custom(m,n,o)):k.custom(m,h,""));return!0})},stop:function(a,b){a&&this.queue([]),this.each(function(){var a=f.timers,c=a.length;b||f._unmark(!0,this);while(c--)a[c].elem===this&&(b&&a[c](!0),a.splice(c,1))}),b||this.dequeue();return this}}),f.each({slideDown:cq("show",1),slideUp:cq("hide",1),slideToggle:cq("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default,d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue!==!1?f.dequeue(this):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,b,c){function g(a){return d.step(a)}var d=this,e=f.fx;this.startTime=cn||co(),this.start=a,this.end=b,this.unit=c||this.unit||(f.cssNumber[this.prop]?"":"px"),this.now=this.start,this.pos=this.state=0,g.elem=this.elem,g()&&f.timers.push(g)&&!cl&&(cl=setInterval(e.tick,e.interval))},show:function(){this.options.orig[this.prop]=f.style(this.elem,this.prop),this.options.show=!0,this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b=cn||co(),c=!0,d=this.elem,e=this.options,g,h;if(a||b>=e.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),e.animatedProperties[this.prop]=!0;for(g in e.animatedProperties)e.animatedProperties[g]!==!0&&(c=!1);if(c){e.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){d.style["overflow"+b]=e.overflow[a]}),e.hide&&f(d).hide();if(e.hide||e.show)for(var i in e.animatedProperties)f.style(d,i,e.orig[i]);e.complete.call(d)}return!1}e.duration==Infinity?this.now=b:(h=b-this.startTime,this.state=h/e.duration,this.pos=f.easing[e.animatedProperties[this.prop]](this.state,h,0,1,e.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){for(var a=f.timers,b=0;b<a.length;++b)a[b]()||a.splice(b--,1);a.length||f.fx.stop()},interval:13,stop:function(){clearInterval(cl),cl=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit:a.elem[a.prop]=a.now}}}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cs=/^t(?:able|d|h)$/i,ct=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?f.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(d){}var e=b.ownerDocument,g=e.documentElement;if(!c||!f.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=e.body,i=cu(e),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||f.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||f.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:f.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);f.offset.initialize();var c,d=b.offsetParent,e=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(f.offset.supportsFixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===d&&(l+=b.offsetTop,m+=b.offsetLeft,f.offset.doesNotAddBorder&&(!f.offset.doesAddBorderForTableAndCells||!cs.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),e=d,d=b.offsetParent),f.offset.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;f.offset.supportsFixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},f.offset={initialize:function(){var a=c.body,b=c.createElement("div"),d,e,g,h,i=parseFloat(f.css(a,"marginTop"))||0,j="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";f.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),d=b.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,this.doesNotAddBorder=e.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,e.style.position="fixed",e.style.top="20px",this.supportsFixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",this.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),f.offset.initialize=f.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.offset.initialize(),f.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=ct.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!ct.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cu(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cu(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a&&a.style?parseFloat(f.css(a,d,"padding")):null},f.fn["outer"+c]=function(a){var b=this[0];return b&&b.style?parseFloat(f.css(b,d,a?"margin":"border")):null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNaN(j)?i:j}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f})(window);
\ No newline at end of file
/*
* jQuery UI CSS Framework 1.8.13
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Theming/API
*/
/* Layout helpers
----------------------------------*/
.ui-helper-hidden { display: none; }
.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
.ui-helper-clearfix { display: inline-block; }
/* required comment for clearfix to work in Opera \*/
* html .ui-helper-clearfix { height:1%; }
.ui-helper-clearfix { display:block; }
/* end clearfix */
.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
/* Interaction Cues
----------------------------------*/
.ui-state-disabled { cursor: default !important; }
/* Icons
----------------------------------*/
/* states and images */
.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
/* Misc visuals
----------------------------------*/
/* Overlays */
.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
/*
* jQuery UI CSS Framework 1.8.13
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Theming/API
*
* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Trebuchet%20MS,%20Tahoma,%20Verdana,%20Arial,%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=f6a828&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=35&borderColorHeader=e78f08&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=eeeeee&bgTextureContent=03_highlight_soft.png&bgImgOpacityContent=100&borderColorContent=dddddd&fcContent=333333&iconColorContent=222222&bgColorDefault=f6f6f6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=100&borderColorDefault=cccccc&fcDefault=1c94c4&iconColorDefault=ef8c08&bgColorHover=fdf5ce&bgTextureHover=02_glass.png&bgImgOpacityHover=100&borderColorHover=fbcb09&fcHover=c77405&iconColorHover=ef8c08&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=fbd850&fcActive=eb8f00&iconColorActive=ef8c08&bgColorHighlight=ffe45c&bgTextureHighlight=03_highlight_soft.png&bgImgOpacityHighlight=75&borderColorHighlight=fed22f&fcHighlight=363636&iconColorHighlight=228ef1&bgColorError=b81900&bgTextureError=08_diagonals_thick.png&bgImgOpacityError=18&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffd27a&bgColorOverlay=666666&bgTextureOverlay=08_diagonals_thick.png&bgImgOpacityOverlay=20&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=01_flat.png&bgImgOpacityShadow=10&opacityShadow=20&thicknessShadow=5px&offsetTopShadow=-5px&offsetLeftShadow=-5px&cornerRadiusShadow=5px
*/
/* Component containers
----------------------------------*/
.ui-widget { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1.1em; }
.ui-widget .ui-widget { font-size: 1em; }
.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1em; }
.ui-widget-content { border: 1px solid #dddddd; background: #eeeeee url(images/ui-bg_highlight-soft_100_eeeeee_1x100.png) 50% top repeat-x; color: #333333; }
.ui-widget-content a { color: #333333; }
.ui-widget-header { border: 1px solid #e78f08; background: #f6a828 url(images/ui-bg_gloss-wave_35_f6a828_500x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; }
.ui-widget-header a { color: #ffffff; }
/* Interaction states
----------------------------------*/
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #cccccc; background: #f6f6f6 url(images/ui-bg_glass_100_f6f6f6_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #1c94c4; }
.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #1c94c4; text-decoration: none; }
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #fbcb09; background: #fdf5ce url(images/ui-bg_glass_100_fdf5ce_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #c77405; }
.ui-state-hover a, .ui-state-hover a:hover { color: #c77405; text-decoration: none; }
.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #fbd850; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #eb8f00; }
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #eb8f00; text-decoration: none; }
.ui-widget :active { outline: none; }
/* Interaction Cues
----------------------------------*/
.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fed22f; background: #ffe45c url(images/ui-bg_highlight-soft_75_ffe45c_1x100.png) 50% top repeat-x; color: #363636; }
.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #b81900 url(images/ui-bg_diagonals-thick_18_b81900_40x40.png) 50% 50% repeat; color: #ffffff; }
.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #ffffff; }
.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #ffffff; }
.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
/* Icons
----------------------------------*/
/* states and images */
.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
.ui-widget-header .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); }
.ui-state-default .ui-icon { background-image: url(images/ui-icons_ef8c08_256x240.png); }
.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_ef8c08_256x240.png); }
.ui-state-active .ui-icon {background-image: url(images/ui-icons_ef8c08_256x240.png); }
.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_228ef1_256x240.png); }
.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_ffd27a_256x240.png); }
/* positioning */
.ui-icon-carat-1-n { background-position: 0 0; }
.ui-icon-carat-1-ne { background-position: -16px 0; }
.ui-icon-carat-1-e { background-position: -32px 0; }
.ui-icon-carat-1-se { background-position: -48px 0; }
.ui-icon-carat-1-s { background-position: -64px 0; }
.ui-icon-carat-1-sw { background-position: -80px 0; }
.ui-icon-carat-1-w { background-position: -96px 0; }
.ui-icon-carat-1-nw { background-position: -112px 0; }
.ui-icon-carat-2-n-s { background-position: -128px 0; }
.ui-icon-carat-2-e-w { background-position: -144px 0; }
.ui-icon-triangle-1-n { background-position: 0 -16px; }
.ui-icon-triangle-1-ne { background-position: -16px -16px; }
.ui-icon-triangle-1-e { background-position: -32px -16px; }
.ui-icon-triangle-1-se { background-position: -48px -16px; }
.ui-icon-triangle-1-s { background-position: -64px -16px; }
.ui-icon-triangle-1-sw { background-position: -80px -16px; }
.ui-icon-triangle-1-w { background-position: -96px -16px; }
.ui-icon-triangle-1-nw { background-position: -112px -16px; }
.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
.ui-icon-arrow-1-n { background-position: 0 -32px; }
.ui-icon-arrow-1-ne { background-position: -16px -32px; }
.ui-icon-arrow-1-e { background-position: -32px -32px; }
.ui-icon-arrow-1-se { background-position: -48px -32px; }
.ui-icon-arrow-1-s { background-position: -64px -32px; }
.ui-icon-arrow-1-sw { background-position: -80px -32px; }
.ui-icon-arrow-1-w { background-position: -96px -32px; }
.ui-icon-arrow-1-nw { background-position: -112px -32px; }
.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
.ui-icon-arrow-4 { background-position: 0 -80px; }
.ui-icon-arrow-4-diag { background-position: -16px -80px; }
.ui-icon-extlink { background-position: -32px -80px; }
.ui-icon-newwin { background-position: -48px -80px; }
.ui-icon-refresh { background-position: -64px -80px; }
.ui-icon-shuffle { background-position: -80px -80px; }
.ui-icon-transfer-e-w { background-position: -96px -80px; }
.ui-icon-transferthick-e-w { background-position: -112px -80px; }
.ui-icon-folder-collapsed { background-position: 0 -96px; }
.ui-icon-folder-open { background-position: -16px -96px; }
.ui-icon-document { background-position: -32px -96px; }
.ui-icon-document-b { background-position: -48px -96px; }
.ui-icon-note { background-position: -64px -96px; }
.ui-icon-mail-closed { background-position: -80px -96px; }
.ui-icon-mail-open { background-position: -96px -96px; }
.ui-icon-suitcase { background-position: -112px -96px; }
.ui-icon-comment { background-position: -128px -96px; }
.ui-icon-person { background-position: -144px -96px; }
.ui-icon-print { background-position: -160px -96px; }
.ui-icon-trash { background-position: -176px -96px; }
.ui-icon-locked { background-position: -192px -96px; }
.ui-icon-unlocked { background-position: -208px -96px; }
.ui-icon-bookmark { background-position: -224px -96px; }
.ui-icon-tag { background-position: -240px -96px; }
.ui-icon-home { background-position: 0 -112px; }
.ui-icon-flag { background-position: -16px -112px; }
.ui-icon-calendar { background-position: -32px -112px; }
.ui-icon-cart { background-position: -48px -112px; }
.ui-icon-pencil { background-position: -64px -112px; }
.ui-icon-clock { background-position: -80px -112px; }
.ui-icon-disk { background-position: -96px -112px; }
.ui-icon-calculator { background-position: -112px -112px; }
.ui-icon-zoomin { background-position: -128px -112px; }
.ui-icon-zoomout { background-position: -144px -112px; }
.ui-icon-search { background-position: -160px -112px; }
.ui-icon-wrench { background-position: -176px -112px; }
.ui-icon-gear { background-position: -192px -112px; }
.ui-icon-heart { background-position: -208px -112px; }
.ui-icon-star { background-position: -224px -112px; }
.ui-icon-link { background-position: -240px -112px; }
.ui-icon-cancel { background-position: 0 -128px; }
.ui-icon-plus { background-position: -16px -128px; }
.ui-icon-plusthick { background-position: -32px -128px; }
.ui-icon-minus { background-position: -48px -128px; }
.ui-icon-minusthick { background-position: -64px -128px; }
.ui-icon-close { background-position: -80px -128px; }
.ui-icon-closethick { background-position: -96px -128px; }
.ui-icon-key { background-position: -112px -128px; }
.ui-icon-lightbulb { background-position: -128px -128px; }
.ui-icon-scissors { background-position: -144px -128px; }
.ui-icon-clipboard { background-position: -160px -128px; }
.ui-icon-copy { background-position: -176px -128px; }
.ui-icon-contact { background-position: -192px -128px; }
.ui-icon-image { background-position: -208px -128px; }
.ui-icon-video { background-position: -224px -128px; }
.ui-icon-script { background-position: -240px -128px; }
.ui-icon-alert { background-position: 0 -144px; }
.ui-icon-info { background-position: -16px -144px; }
.ui-icon-notice { background-position: -32px -144px; }
.ui-icon-help { background-position: -48px -144px; }
.ui-icon-check { background-position: -64px -144px; }
.ui-icon-bullet { background-position: -80px -144px; }
.ui-icon-radio-off { background-position: -96px -144px; }
.ui-icon-radio-on { background-position: -112px -144px; }
.ui-icon-pin-w { background-position: -128px -144px; }
.ui-icon-pin-s { background-position: -144px -144px; }
.ui-icon-play { background-position: 0 -160px; }
.ui-icon-pause { background-position: -16px -160px; }
.ui-icon-seek-next { background-position: -32px -160px; }
.ui-icon-seek-prev { background-position: -48px -160px; }
.ui-icon-seek-end { background-position: -64px -160px; }
.ui-icon-seek-start { background-position: -80px -160px; }
/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
.ui-icon-seek-first { background-position: -80px -160px; }
.ui-icon-stop { background-position: -96px -160px; }
.ui-icon-eject { background-position: -112px -160px; }
.ui-icon-volume-off { background-position: -128px -160px; }
.ui-icon-volume-on { background-position: -144px -160px; }
.ui-icon-power { background-position: 0 -176px; }
.ui-icon-signal-diag { background-position: -16px -176px; }
.ui-icon-signal { background-position: -32px -176px; }
.ui-icon-battery-0 { background-position: -48px -176px; }
.ui-icon-battery-1 { background-position: -64px -176px; }
.ui-icon-battery-2 { background-position: -80px -176px; }
.ui-icon-battery-3 { background-position: -96px -176px; }
.ui-icon-circle-plus { background-position: 0 -192px; }
.ui-icon-circle-minus { background-position: -16px -192px; }
.ui-icon-circle-close { background-position: -32px -192px; }
.ui-icon-circle-triangle-e { background-position: -48px -192px; }
.ui-icon-circle-triangle-s { background-position: -64px -192px; }
.ui-icon-circle-triangle-w { background-position: -80px -192px; }
.ui-icon-circle-triangle-n { background-position: -96px -192px; }
.ui-icon-circle-arrow-e { background-position: -112px -192px; }
.ui-icon-circle-arrow-s { background-position: -128px -192px; }
.ui-icon-circle-arrow-w { background-position: -144px -192px; }
.ui-icon-circle-arrow-n { background-position: -160px -192px; }
.ui-icon-circle-zoomin { background-position: -176px -192px; }
.ui-icon-circle-zoomout { background-position: -192px -192px; }
.ui-icon-circle-check { background-position: -208px -192px; }
.ui-icon-circlesmall-plus { background-position: 0 -208px; }
.ui-icon-circlesmall-minus { background-position: -16px -208px; }
.ui-icon-circlesmall-close { background-position: -32px -208px; }
.ui-icon-squaresmall-plus { background-position: -48px -208px; }
.ui-icon-squaresmall-minus { background-position: -64px -208px; }
.ui-icon-squaresmall-close { background-position: -80px -208px; }
.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
/* Misc visuals
----------------------------------*/
/* Corner radius */
.ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; }
.ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; }
.ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; }
.ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
.ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; }
.ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
.ui-corner-right { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
.ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; }
.ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; }
/* Overlays */
.ui-widget-overlay { background: #666666 url(images/ui-bg_diagonals-thick_20_666666_40x40.png) 50% 50% repeat; opacity: .50;filter:Alpha(Opacity=50); }
.ui-widget-shadow { margin: -5px 0 0 -5px; padding: 5px; background: #000000 url(images/ui-bg_flat_10_000000_40x100.png) 50% 50% repeat-x; opacity: .20;filter:Alpha(Opacity=20); -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; }/*
* jQuery UI Resizable 1.8.13
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Resizable#theming
*/
.ui-resizable { position: relative;}
.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;
/* http://bugs.jqueryui.com/ticket/7233
- Resizable: resizable handles fail to work in IE if transparent and content overlaps
*/
background-image:url(data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=);
}
.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/*
* jQuery UI Selectable 1.8.13
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Selectable#theming
*/
.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
/*
* jQuery UI Accordion 1.8.13
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Accordion#theming
*/
/* IE/Win - Fix animation bug - #4615 */
.ui-accordion { width: 100%; }
.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
.ui-accordion .ui-accordion-li-fix { display: inline; }
.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
.ui-accordion .ui-accordion-content-active { display: block; }
/*
* jQuery UI Autocomplete 1.8.13
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Autocomplete#theming
*/
.ui-autocomplete { position: absolute; cursor: default; }
/* workarounds */
* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
/*
* jQuery UI Menu 1.8.13
*
* Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Menu#theming
*/
.ui-menu {
list-style:none;
padding: 2px;
margin: 0;
display:block;
float: left;
}
.ui-menu .ui-menu {
margin-top: -3px;
}
.ui-menu .ui-menu-item {
margin:0;
padding: 0;
zoom: 1;
float: left;
clear: left;
width: 100%;
}
.ui-menu .ui-menu-item a {
text-decoration:none;
display:block;
padding:.2em .4em;
line-height:1.5;
zoom:1;
}
.ui-menu .ui-menu-item a.ui-state-hover,
.ui-menu .ui-menu-item a.ui-state-active {
font-weight: normal;
margin: -1px;
}
/*
* jQuery UI Button 1.8.13
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Button#theming
*/
.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
.ui-button-icons-only { width: 3.4em; }
button.ui-button-icons-only { width: 3.7em; }
/*button text element */
.ui-button .ui-button-text { display: block; line-height: 1.4; }
.ui-button-text-only .ui-button-text { padding: .4em 1em; }
.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
/* no icon support for input elements, provide padding by default */
input.ui-button { padding: .4em 1em; }
/*button icon element(s) */
.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
/*button sets*/
.ui-buttonset { margin-right: 7px; }
.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
/* workarounds */
button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
/*
* jQuery UI Dialog 1.8.13
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Dialog#theming
*/
.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }
.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; }
.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; }
.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
.ui-draggable .ui-dialog-titlebar { cursor: move; }
/*
* jQuery UI Slider 1.8.13
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Slider#theming
*/
.ui-slider { position: relative; text-align: left; }
.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
.ui-slider-horizontal { height: .8em; }
.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
.ui-slider-horizontal .ui-slider-range-min { left: 0; }
.ui-slider-horizontal .ui-slider-range-max { right: 0; }
.ui-slider-vertical { width: .8em; height: 100px; }
.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
.ui-slider-vertical .ui-slider-range-max { top: 0; }/*
* jQuery UI Tabs 1.8.13
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Tabs#theming
*/
.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
.ui-tabs .ui-tabs-hide { display: none !important; }
/*
* jQuery UI Datepicker 1.8.13
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Datepicker#theming
*/
.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
.ui-datepicker .ui-datepicker-prev { left:2px; }
.ui-datepicker .ui-datepicker-next { right:2px; }
.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
.ui-datepicker .ui-datepicker-next-hover { right:1px; }
.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
.ui-datepicker select.ui-datepicker-month,
.ui-datepicker select.ui-datepicker-year { width: 49%;}
.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
.ui-datepicker td { border: 0; padding: 1px; }
.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
/* with multiple calendars */
.ui-datepicker.ui-datepicker-multi { width:auto; }
.ui-datepicker-multi .ui-datepicker-group { float:left; }
.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
.ui-datepicker-row-break { clear:both; width:100%; }
/* RTL support */
.ui-datepicker-rtl { direction: rtl; }
.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
.ui-datepicker-rtl .ui-datepicker-group { float:right; }
.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
.ui-datepicker-cover {
display: none; /*sorry for IE5*/
display/**/: block; /*sorry for IE5*/
position: absolute; /*must have*/
z-index: -1; /*must have*/
filter: mask(); /*must have*/
top: -4px; /*must have*/
left: -4px; /*must have*/
width: 200px; /*must have*/
height: 200px; /*must have*/
}/*
* jQuery UI Progressbar 1.8.13
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Progressbar#theming
*/
.ui-progressbar { height:2em; text-align: left; }
.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
function jquery_list(list, msg) {
var selectBoxContainer = $("#"+list);
//add the header box <div> to the list
selectBoxContainer.append("<div></div>");
//assign the default message to the list header
var selectBox = selectBoxContainer.find('div');
selectBox.html(msg);
selectBoxContainer.attr('value',msg);
//process the list
var dropDown = selectBoxContainer.find('ul');
//dropDown.css({position:'absolute'});
selectBoxContainer.append(dropDown.hide());
dropDown.bind('show',function(){
if(dropDown.is(':animated')){
return false;
}
selectBox.addClass('expanded');
dropDown.slideDown();
}).bind('hide',function(){
if(dropDown.is(':animated')){
return false;
}
selectBox.removeClass('expanded');
dropDown.slideUp();
}).bind('toggle',function(){
if(selectBox.hasClass('expanded')){
dropDown.trigger('hide');
}
else dropDown.trigger('show');
});
selectBox.click(function(){
dropDown.trigger('toggle');
return false;
});
$(document).click(function(){
dropDown.trigger('hide');
});
//process all the list elements
dropDown.find('li').each(function(i) {
var li = $(this);
li.click(function(){
selectBox.html(li.html());
selectBoxContainer.attr('value',li.html());
dropDown.trigger('hide');
return false;
});
});
}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
/* required styles */
.leaflet-pane,
.leaflet-tile,
.leaflet-marker-icon,
.leaflet-marker-shadow,
.leaflet-tile-container,
.leaflet-pane > svg,
.leaflet-pane > canvas,
.leaflet-zoom-box,
.leaflet-image-layer,
.leaflet-layer {
position: absolute;
left: 0;
top: 0;
}
.leaflet-container {
overflow: hidden;
}
.leaflet-tile,
.leaflet-marker-icon,
.leaflet-marker-shadow {
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
-webkit-user-drag: none;
}
/* Safari renders non-retina tile on retina better with this, but Chrome is worse */
.leaflet-safari .leaflet-tile {
image-rendering: -webkit-optimize-contrast;
}
/* hack that prevents hw layers "stretching" when loading new tiles */
.leaflet-safari .leaflet-tile-container {
width: 1600px;
height: 1600px;
-webkit-transform-origin: 0 0;
}
.leaflet-marker-icon,
.leaflet-marker-shadow {
display: block;
}
/* .leaflet-container svg: reset svg max-width decleration shipped in Joomla! (joomla.org) 3.x */
/* .leaflet-container img: map is broken in FF if you have max-width: 100% on tiles */
.leaflet-container .leaflet-overlay-pane svg,
.leaflet-container .leaflet-marker-pane img,
.leaflet-container .leaflet-shadow-pane img,
.leaflet-container .leaflet-tile-pane img,
.leaflet-container img.leaflet-image-layer {
max-width: none !important;
}
.leaflet-container.leaflet-touch-zoom {
-ms-touch-action: pan-x pan-y;
touch-action: pan-x pan-y;
}
.leaflet-container.leaflet-touch-drag {
-ms-touch-action: pinch-zoom;
}
.leaflet-container.leaflet-touch-drag.leaflet-touch-drag {
-ms-touch-action: none;
touch-action: none;
}
.leaflet-tile {
filter: inherit;
visibility: hidden;
}
.leaflet-tile-loaded {
visibility: inherit;
}
.leaflet-zoom-box {
width: 0;
height: 0;
-moz-box-sizing: border-box;
box-sizing: border-box;
z-index: 800;
}
/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */
.leaflet-overlay-pane svg {
-moz-user-select: none;
}
.leaflet-pane { z-index: 400; }
.leaflet-tile-pane { z-index: 200; }
.leaflet-overlay-pane { z-index: 400; }
.leaflet-shadow-pane { z-index: 500; }
.leaflet-marker-pane { z-index: 600; }
.leaflet-tooltip-pane { z-index: 650; }
.leaflet-popup-pane { z-index: 700; }
.leaflet-map-pane canvas { z-index: 100; }
.leaflet-map-pane svg { z-index: 200; }
.leaflet-vml-shape {
width: 1px;
height: 1px;
}
.lvml {
behavior: url(#default#VML);
display: inline-block;
position: absolute;
}
/* control positioning */
.leaflet-control {
position: relative;
z-index: 800;
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
pointer-events: auto;
}
.leaflet-top,
.leaflet-bottom {
position: absolute;
z-index: 1000;
pointer-events: none;
}
.leaflet-top {
top: 0;
}
.leaflet-right {
right: 0;
}
.leaflet-bottom {
bottom: 0;
}
.leaflet-left {
left: 0;
}
.leaflet-control {
float: left;
clear: both;
}
.leaflet-right .leaflet-control {
float: right;
}
.leaflet-top .leaflet-control {
margin-top: 10px;
}
.leaflet-bottom .leaflet-control {
margin-bottom: 10px;
}
.leaflet-left .leaflet-control {
margin-left: 10px;
}
.leaflet-right .leaflet-control {
margin-right: 10px;
}
/* zoom and fade animations */
.leaflet-fade-anim .leaflet-tile {
will-change: opacity;
}
.leaflet-fade-anim .leaflet-popup {
opacity: 0;
-webkit-transition: opacity 0.2s linear;
-moz-transition: opacity 0.2s linear;
-o-transition: opacity 0.2s linear;
transition: opacity 0.2s linear;
}
.leaflet-fade-anim .leaflet-map-pane .leaflet-popup {
opacity: 1;
}
.leaflet-zoom-animated {
-webkit-transform-origin: 0 0;
-ms-transform-origin: 0 0;
transform-origin: 0 0;
}
.leaflet-zoom-anim .leaflet-zoom-animated {
will-change: transform;
}
.leaflet-zoom-anim .leaflet-zoom-animated {
-webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1);
-moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1);
-o-transition: -o-transform 0.25s cubic-bezier(0,0,0.25,1);
transition: transform 0.25s cubic-bezier(0,0,0.25,1);
}
.leaflet-zoom-anim .leaflet-tile,
.leaflet-pan-anim .leaflet-tile {
-webkit-transition: none;
-moz-transition: none;
-o-transition: none;
transition: none;
}
.leaflet-zoom-anim .leaflet-zoom-hide {
visibility: hidden;
}
/* cursors */
.leaflet-interactive {
cursor: pointer;
}
.leaflet-grab {
cursor: -webkit-grab;
cursor: -moz-grab;
}
.leaflet-crosshair,
.leaflet-crosshair .leaflet-interactive {
cursor: crosshair;
}
.leaflet-popup-pane,
.leaflet-control {
cursor: auto;
}
.leaflet-dragging .leaflet-grab,
.leaflet-dragging .leaflet-grab .leaflet-interactive,
.leaflet-dragging .leaflet-marker-draggable {
cursor: move;
cursor: -webkit-grabbing;
cursor: -moz-grabbing;
}
/* marker & overlays interactivity */
.leaflet-marker-icon,
.leaflet-marker-shadow,
.leaflet-image-layer,
.leaflet-pane > svg path,
.leaflet-tile-container {
pointer-events: none;
}
.leaflet-marker-icon.leaflet-interactive,
.leaflet-image-layer.leaflet-interactive,
.leaflet-pane > svg path.leaflet-interactive {
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
pointer-events: auto;
}
/* visual tweaks */
.leaflet-container {
background: #ddd;
outline: 0;
}
.leaflet-container a {
color: #0078A8;
}
.leaflet-container a.leaflet-active {
outline: 2px solid orange;
}
.leaflet-zoom-box {
border: 2px dotted #38f;
background: rgba(255,255,255,0.5);
}
/* general typography */
.leaflet-container {
font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif;
}
/* general toolbar styles */
.leaflet-bar {
box-shadow: 0 1px 5px rgba(0,0,0,0.65);
border-radius: 4px;
}
.leaflet-bar a,
.leaflet-bar a:hover {
background-color: #fff;
border-bottom: 1px solid #ccc;
width: 26px;
height: 26px;
line-height: 26px;
display: block;
text-align: center;
text-decoration: none;
color: black;
}
.leaflet-bar a,
.leaflet-control-layers-toggle {
background-position: 50% 50%;
background-repeat: no-repeat;
display: block;
}
.leaflet-bar a:hover {
background-color: #f4f4f4;
}
.leaflet-bar a:first-child {
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
.leaflet-bar a:last-child {
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
border-bottom: none;
}
.leaflet-bar a.leaflet-disabled {
cursor: default;
background-color: #f4f4f4;
color: #bbb;
}
.leaflet-touch .leaflet-bar a {
width: 30px;
height: 30px;
line-height: 30px;
}
/* zoom control */
.leaflet-control-zoom-in,
.leaflet-control-zoom-out {
font: bold 18px 'Lucida Console', Monaco, monospace;
text-indent: 1px;
}
.leaflet-control-zoom-out {
font-size: 20px;
}
.leaflet-touch .leaflet-control-zoom-in {
font-size: 22px;
}
.leaflet-touch .leaflet-control-zoom-out {
font-size: 24px;
}
/* layers control */
.leaflet-control-layers {
box-shadow: 0 1px 5px rgba(0,0,0,0.4);
background: #fff;
border-radius: 5px;
}
.leaflet-control-layers-toggle {
background-image: url(images/layers.png);
width: 36px;
height: 36px;
}
.leaflet-retina .leaflet-control-layers-toggle {
background-image: url(images/layers-2x.png);
background-size: 26px 26px;
}
.leaflet-touch .leaflet-control-layers-toggle {
width: 44px;
height: 44px;
}
.leaflet-control-layers .leaflet-control-layers-list,
.leaflet-control-layers-expanded .leaflet-control-layers-toggle {
display: none;
}
.leaflet-control-layers-expanded .leaflet-control-layers-list {
display: block;
position: relative;
}
.leaflet-control-layers-expanded {
padding: 6px 10px 6px 6px;
color: #333;
background: #fff;
}
.leaflet-control-layers-scrollbar {
overflow-y: scroll;
padding-right: 5px;
}
.leaflet-control-layers-selector {
margin-top: 2px;
position: relative;
top: 1px;
}
.leaflet-control-layers label {
display: block;
}
.leaflet-control-layers-separator {
height: 0;
border-top: 1px solid #ddd;
margin: 5px -10px 5px -6px;
}
/* Default icon URLs */
.leaflet-default-icon-path {
background-image: url(images/marker-icon.png);
}
/* attribution and scale controls */
.leaflet-container .leaflet-control-attribution {
background: #fff;
background: rgba(255, 255, 255, 0.7);
margin: 0;
}
.leaflet-control-attribution,
.leaflet-control-scale-line {
padding: 0 5px;
color: #333;
}
.leaflet-control-attribution a {
text-decoration: none;
}
.leaflet-control-attribution a:hover {
text-decoration: underline;
}
.leaflet-container .leaflet-control-attribution,
.leaflet-container .leaflet-control-scale {
font-size: 11px;
}
.leaflet-left .leaflet-control-scale {
margin-left: 5px;
}
.leaflet-bottom .leaflet-control-scale {
margin-bottom: 5px;
}
.leaflet-control-scale-line {
border: 2px solid #777;
border-top: none;
line-height: 1.1;
padding: 2px 5px 1px;
font-size: 11px;
white-space: nowrap;
overflow: hidden;
-moz-box-sizing: border-box;
box-sizing: border-box;
background: #fff;
background: rgba(255, 255, 255, 0.5);
}
.leaflet-control-scale-line:not(:first-child) {
border-top: 2px solid #777;
border-bottom: none;
margin-top: -2px;
}
.leaflet-control-scale-line:not(:first-child):not(:last-child) {
border-bottom: 2px solid #777;
}
.leaflet-touch .leaflet-control-attribution,
.leaflet-touch .leaflet-control-layers,
.leaflet-touch .leaflet-bar {
box-shadow: none;
}
.leaflet-touch .leaflet-control-layers,
.leaflet-touch .leaflet-bar {
border: 2px solid rgba(0,0,0,0.2);
background-clip: padding-box;
}
/* popup */
.leaflet-popup {
position: absolute;
text-align: center;
margin-bottom: 20px;
}
.leaflet-popup-content-wrapper {
padding: 1px;
text-align: left;
border-radius: 12px;
}
.leaflet-popup-content {
margin: 13px 19px;
line-height: 1.4;
}
.leaflet-popup-content p {
margin: 18px 0;
}
.leaflet-popup-tip-container {
width: 40px;
height: 20px;
position: absolute;
left: 50%;
margin-left: -20px;
overflow: hidden;
pointer-events: none;
}
.leaflet-popup-tip {
width: 17px;
height: 17px;
padding: 1px;
margin: -10px auto 0;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-ms-transform: rotate(45deg);
-o-transform: rotate(45deg);
transform: rotate(45deg);
}
.leaflet-popup-content-wrapper,
.leaflet-popup-tip {
background: white;
color: #333;
box-shadow: 0 3px 14px rgba(0,0,0,0.4);
}
.leaflet-container a.leaflet-popup-close-button {
position: absolute;
top: 0;
right: 0;
padding: 4px 4px 0 0;
border: none;
text-align: center;
width: 18px;
height: 14px;
font: 16px/14px Tahoma, Verdana, sans-serif;
color: #c3c3c3;
text-decoration: none;
font-weight: bold;
background: transparent;
}
.leaflet-container a.leaflet-popup-close-button:hover {
color: #999;
}
.leaflet-popup-scrolled {
overflow: auto;
border-bottom: 1px solid #ddd;
border-top: 1px solid #ddd;
}
.leaflet-oldie .leaflet-popup-content-wrapper {
zoom: 1;
}
.leaflet-oldie .leaflet-popup-tip {
width: 24px;
margin: 0 auto;
-ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";
filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);
}
.leaflet-oldie .leaflet-popup-tip-container {
margin-top: -1px;
}
.leaflet-oldie .leaflet-control-zoom,
.leaflet-oldie .leaflet-control-layers,
.leaflet-oldie .leaflet-popup-content-wrapper,
.leaflet-oldie .leaflet-popup-tip {
border: 1px solid #999;
}
/* div icon */
.leaflet-div-icon {
background: #fff;
border: 1px solid #666;
}
/* Tooltip */
/* Base styles for the element that has a tooltip */
.leaflet-tooltip {
position: absolute;
padding: 6px;
background-color: #fff;
border: 1px solid #fff;
border-radius: 3px;
color: #222;
white-space: nowrap;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
pointer-events: none;
box-shadow: 0 1px 3px rgba(0,0,0,0.4);
}
.leaflet-tooltip.leaflet-clickable {
cursor: pointer;
pointer-events: auto;
}
.leaflet-tooltip-top:before,
.leaflet-tooltip-bottom:before,
.leaflet-tooltip-left:before,
.leaflet-tooltip-right:before {
position: absolute;
pointer-events: none;
border: 6px solid transparent;
background: transparent;
content: "";
}
/* Directions */
.leaflet-tooltip-bottom {
margin-top: 6px;
}
.leaflet-tooltip-top {
margin-top: -6px;
}
.leaflet-tooltip-bottom:before,
.leaflet-tooltip-top:before {
left: 50%;
margin-left: -6px;
}
.leaflet-tooltip-top:before {
bottom: 0;
margin-bottom: -12px;
border-top-color: #fff;
}
.leaflet-tooltip-bottom:before {
top: 0;
margin-top: -12px;
margin-left: -6px;
border-bottom-color: #fff;
}
.leaflet-tooltip-left {
margin-left: -6px;
}
.leaflet-tooltip-right {
margin-left: 6px;
}
.leaflet-tooltip-left:before,
.leaflet-tooltip-right:before {
top: 50%;
margin-top: -6px;
}
.leaflet-tooltip-left:before {
right: 0;
margin-right: -12px;
border-left-color: #fff;
}
.leaflet-tooltip-right:before {
left: 0;
margin-left: -12px;
border-right-color: #fff;
}
This source diff could not be displayed because it is too large. You can view the blob instead.
.list
{
width: 260px;
height: 20px;
line-height: 20px; /*should be the same as height*/
font-size: 14px;
}
.list li
{
list-style-type: none;
display: block;
position: relative;
top: 8px;
left: -30px;
border: 1px dotted #eaeaea;
background: white;
padding-left: 5px;
}
.list li:hover
{
background: -webkit-gradient(linear, left top, left bottom, from(rgba(180,180,180,1)), to(rgba(210,210,210,1))); /* for webkit browsers */
background: -moz-linear-gradient(top, rgba(210,210,210,1), rgba(180,180,180,1)); /* for firefox 3.6+ */
}
.list div
{
position:absolute;
width: 300px;
height: 20px;
background: -webkit-gradient(linear, left top, left bottom, from(rgba(210,210,210,1)), to(rgba(180,180,180,1))); /* for webkit browsers */
background: -moz-linear-gradient(top, rgba(180,180,180,1), rgba(210,210,210,1)); /* for firefox 3.6+ */
text-align:center;
border: 1px solid black;
-moz-border-radius:3px;
-webkit-border-radius:3px;
border-radius:3px;
}
.list div:hover
{
background: -webkit-gradient(linear, left top, left bottom, from(rgba(180,180,180,1)), to(rgba(210,210,210,1))); /* for webkit browsers */
background: -moz-linear-gradient(top, rgba(210,210,210,1), rgba(180,180,180,1)); /* for firefox 3.6+ */
color:rgba(255,255,255,1);
}
.list div:active
{
background: -webkit-gradient(linear, left top, left bottom, from(rgba(210,210,210,1)), to(rgba(180,180,180,1))); /* for webkit browsers */
background: -moz-linear-gradient(top, rgba(180,180,180,1), rgba(210,210,210,1)); /* for firefox 3.6+ */
color:rgba(255,255,255,1);
}
\ No newline at end of file
[Dolphin]
Timestamp=2011,3,10,17,38,55
ViewMode=1
#all_wrap {
position: absolute;
bottom: 3px;
right: 3px;
}
#map_wrap,#osmap_wrap {
position: relative;
margin: 2px;
}
#map, #osmap {
width: 400px;
height: 300px;
font-size: 12px;
}
#map_header, #osmap_header {
display: inline-block;
padding : 2px 5px 2px 5px;
margin : 2px 2px 2px 0px;
}
#map_header:hover, #table_header:hover, #osmap_header:hover {
color: white;
cursor: pointer;
}
#map_div, #osmap_div {
padding : 2px;
background: white;
/*float: right;*/
}
.grey {
background: rgba(150,150,150,0.5);
}
#status { font-family: 'Dancing Script', arial, serif; }
.maps_header {
/*background: rgba(255,255,255,0.7);*/
background: -webkit-gradient(linear, left top, left bottom, from(rgba(255,255,255,0.8)), to(rgba(225,225,225,0.5))); /* for webkit browsers */
background: -moz-linear-gradient(top, rgba(255,255,255,0.8), rgba(255,255,255,0.5)); /* for firefox 3.6+ */
-moz-box-shadow: 2px 2px 2px black;
-webkit-box-shadow: 2px 2px 2px black;
box-shadow: 2px 2px 2px black;
-moz-border-radius:3px;
-webkit-border-radius:3px;
border-radius:3px;
}
\ No newline at end of file
/*
*! -----------------------------------------------------------------------------**
*! FILE NAME : modify_kml.js
*! DESCRIPTION: Sends modified map data to the server
*! Copyright (C) 2011 Elphel, Inc.
*!
*! -----------------------------------------------------------------------------**
*!
*! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------**
*!
*/
function generateKML(nodes){
var return_string = "<kml xmlns='http://earth.google.com/kml/2.2'>\n<Document>\n";
for(var i in nodes) {
return_string += "\
\t<PhotoOverlay>\n\
\t\t<name>"+nodes[i].name+"</name>\n\
\t\t<description>"+nodes[i].description+"</description>\n\
\t\t<visibility>"+(nodes[i].visibility?1:0)+"</visibility>\n\
\t\t<Camera>\n\
\t\t\t<longitude>"+nodes[i].longitude+"</longitude>\n\
\t\t\t<latitude>"+nodes[i].latitude+"</latitude>\n\
\t\t\t<altitude>"+nodes[i].altitude+"</altitude>\n\
\t\t\t<heading>"+nodes[i].heading+"</heading>\n\
\t\t\t<tilt>"+nodes[i].tilt+"</tilt>\n\
\t\t\t<roll>"+nodes[i].roll+"</roll>\n\
\t\t</Camera>\n\
\t\t<Icon>\n\
\t\t\t<href>"+nodes[i].href+"</href>\n\
\t\t</Icon>\n";
if (typeof(nodes[i].v3d)!='undefined') {
return_string += "\
\t\t<ExtendedData>\n\
\t\t\t<Visibility3d>\n";
for (var j in nodes[i].v3d) {
return_string += "\
\t\t\t\t<v3Range>\n";
if (typeof(nodes[i].v3d[j].from)!='undefined') return_string +="\t\t\t\t\t\t<from>"+nodes[i].v3d[j].from+"</from>\n";
if (typeof(nodes[i].v3d[j].to) !='undefined') return_string +="\t\t\t\t\t\t<to>"+ nodes[i].v3d[j].to+ "</to>\n";
return_string += "\
\t\t\t\t</v3Range>\n";
}
return_string += "\
\t\t\t</Visibility3d>\n\
\t\t</ExtendedData>\n";
}
return_string += "\
\t</PhotoOverlay>\n";
}
return_string += "</Document>\n</kml>";
return return_string;
}
function postKmlData(filename, xml) {
$.ajax({
url: "modify_kml.php?kml="+filename,
type: "POST",
dataType: "xml",
data: xml,
async:false,
complete: function(response){},
contentType: "text/xml; charset=\"utf-8\""
});
}
\ No newline at end of file
/*!***************************************************************************
*! FILE NAME : os_map.js
*! DESCRIPTION: functions for OpenLayers Open Street Map API
*! Copyright (C) 2011 Elphel, Inc
*! -----------------------------------------------------------------------------**
*!
*! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------**
*!
*! $Log: os_map.js,v $
*!
*/
// globals for map
var osm_markers = new Array();
var kml_response;
var map_points = new Array();
var N=0;
var osmap;
var osm_points = new Array();
var osm_CurrentMarker;
var osm_zoom=18;
var icon_eyesis4pi;
var icon_dot_green;
var icon_dot_blue;
function osm_init(){
console.log("map init!");
icon_eyesis4pi = L.icon({
iconUrl: "files/map_icons/eyesis4pi_icon.png",
iconSize: [30,70],
iconAnchor: [15,70]
});
icon_dot_green = L.icon({
iconUrl: "files/map_icons/small_dot.png",
iconSize: [12,12],
iconAnchor: [6,6]
});
icon_dot_blue = L.icon({
iconUrl: "files/map_icons/small_dot_blue.png",
iconSize: [12,12],
iconAnchor: [6,6]
});
osmap = L.map('osmap').setView([40.723407, -111.932970], 12);
L.tileLayer('http://a.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: 'Map data and images &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>',
maxZoom: osm_zoom,
}).addTo(osmap);
/*
L.marker([40.723407, -111.932970],{icon:icon_eyesis4pi}).addTo(osmap).on("click",function(e){
console.log("Youclicked "+e.latlng);
this.setIcon(icon_dot_green);
});
*/
}
function osm_place_points(){
console.log("Place points!");
osm_points = new Array();
for (var i=map_points.length-1;i>=0;i--) {
osm_place_point(map_points[i],i);
}
osm_CurrentMarker = map_points[0];
}
function osm_place_point(mark,n) {
var icon;
if (n==0) {
osmap.setView([mark.latitude, mark.longitude]);
}
if (n==0) var icon = icon_eyesis4pi;
else var icon = icon_dot_green;
osm_create_marker(mark,icon);
}
function osm_create_marker(mark,icon) {
var point = L.marker([mark.latitude, mark.longitude],{icon:icon});
$(point).attr("index",mark.thisnode);
point.on("click",function(){
//clearInterval(intvl);
//osm_set_current_position(mark);
osm_remove_points();
//set_image_number(mark.thisnode);
getMapNodes(serverURL,mark.href);
});
point.on("mouseover",function(){
if (mark.href!=osm_CurrentMarker.href) this.setIcon(icon_dot_blue);
});
point.on("mouseout",function(){
if (mark.href!=osm_CurrentMarker.href) this.setIcon(icon_dot_green);
});
//point.addTo(osmap);
osmap.addLayer(point);
osm_points[mark.thisnode] = point;
}
function osm_set_current_position(mark) {
console.log("setting center:");
console.log(mark);
osm_set_icon(osm_CurrentMarker,icon_dot_green);
osm_set_icon(mark,icon_eyesis4pi);
osm_CurrentMarker = mark;
}
function osm_remove_marker(i) {
osmap.removeLayer(osm_points[i]);
}
function osm_set_icon(mark,icon) {
osm_points[mark.thisnode].setIcon(icon);
}
function osm_remove_points(){
console.log("Remove points! "+map_points.length);
for (i=0;i<map_points.length;i++) {
osm_remove_marker(i);
}
}
body{
font-family:"Times New Roman", Times, serif;
}
table{
}
th{
border: 0px solid black;
background: rgba(120,200,120,0.5);
padding: 5px;
border-radius: 2px;
}
td{
border: 0px solid black;
/*background: rgba(100,200,100,0.1);*/
padding: 2px 10px 2px 10px;
text-align: center;
border-radius: 2px;
}
a:link{
color: rgba(30,100,30,1);
}
a:visited{
color: rgba(50,50,50,1);
}
#main{
position: absolute;
padding: 5px;
}
#route_list{
position: relative;
float: left;
/* width: 450px;
height: 350px;*/
/*background: rgba(100,100,200,0.4);*/
}
#action_list{
position:relative;
float: left;
}
#action_form{
position:relative;
width: 500px;
background: rgba(100,200,100,0.4);
padding: 5px;
margin: 3px;
}
#input_fn{
position: relative;
width: 200px;
border-radius: 3px;
}
#status_box{
position: relative;
background: rgba(100,200,100,0.4);
padding: 5px;
margin: 3px;
}
#status{
width: 454px;
background: white;
}
\ No newline at end of file
/*!*******************************************************************************
*! FILE NAME : pano_index.js
*! DESCRIPTION: get the routes list
*! Copyright (C) 2011 Elphel, Inc
*! -----------------------------------------------------------------------------**
*! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! The four essential freedoms with GNU GPL software:
*! * the freedom to run the program for any purpose
*! * the freedom to study how the program works and change it to make it do what you wish
*! * the freedom to redistribute copies so you can help your neighbor
*! * the freedom to distribute copies of your modified versions to others
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------**
*!
*/
function postRequest(cmd, xml) {
$.ajax({
url: "pano_db_interface.php?cmd="+cmd,
type: "POST",
dataType: "xml",
data: xml,
async:false,
complete: function(response){parse_response(response.responseXML,cmd);},
contentType: "text/xml; charset=\"utf-8\""
});
}
function getRequest(rq,callback) {
$.ajax({
url: rq,
type: "GET",
// async:false,
complete: function(response){callback(response.responseText);},
});
}
var res_arr = Array();
function parse_response(xml,cmd){
var result="";
res_arr = XMLToArray(xml);
if (cmd=="GetRoutesAndKMLs") {
//get also KML files
var table_str = "<table>\
<tr>\
<th>Route ID</th>\
<th>Name</th>\
<th>Description</th>\
<th>Nodes</th>\
<th>KML</th>\
<th>Editable</th>\
</tr>";
for (var i=0;i<res_arr.length;i++){
row_color = "rgba("+(220+60*(i%2))+","+(220+60*(i%2))+","+(220+60*(i%2))+",0.2)";
var tmp_id = (res_arr[i].ID==undefined)?"":res_arr[i].ID;
var tmp_name = (res_arr[i].Name==undefined)?"":res_arr[i].Name;
var tmp_descr = (res_arr[i].Description==undefined)?"":res_arr[i].Description;
var tmp_nodes = (res_arr[i].Nodes==undefined)?"":res_arr[i].Nodes;
var tmp_edit = (res_arr[i].Editable==undefined)?"No":res_arr[i].Editable;
var tmp_kml = tmp_id;
table_str += "<tr id='r"+i+"' style='background:"+row_color+"' onclick='row_click_handler("+i+")'>\
<td><a href='webgl_panorama_editor.html?kml="+tmp_id+"'>"+tmp_id+"</a></td>\
<td><div style='width:150px;'>"+tmp_name+"</div></td>\
<td><div style='width:250px;'>"+tmp_descr+"</div></td>\
<td>"+(+tmp_nodes)+"</td>\
<td><a style='display:none;' href='display_kml.php?id="+tmp_id+"'>"+tmp_id+"</a></td>\
<td>"+tmp_edit+"</td>\
</tr>";
}
table_str +="</table>";
}
$("#route_list").html(table_str);
}
//siuda!
function row_click_handler(i){
if ($("#r"+i).attr('marked')=="true") {
$("#r"+i).attr('marked',"false");
$("#r"+i).css({background:$("#r"+i).attr('old_color')});
}else{
$("#r"+i).attr('marked',"true");
$("#r"+i).attr('old_color',$("#r"+i).css("background-color"));
$("#r"+i).css({background:"rgba(100,200,50,0.8)"});
//disable others
for (var j=0;j<res_arr.length;j++) {
if (i!=j) {
$("#r"+j).css({background:$("#r"+j).attr('old_color')});
$("#r"+j).attr('marked',"false");
}
}
}
}
function create_copy(){
found_marked = false;
$("#status").val("");
for(var i=0;i<res_arr.length;i++){
if ($("#r"+i).attr('marked')=="true") {
found_marked = true;
break;
}
}
if (!found_marked) {
$("#status").val("Please select one of the routes");
return 0;
}
if ($("#input_fn").val()=="") {
$("#status").val("Please enter the copy name");
return 0;
}
if ($("#input_fn").val().substr(-3,3)!="kml") {
$("#status").val("Incorrect file extension");
return 0;
}
if($("#input_fn").val().match(/[\<\>!@#\$%^&\*,/]+/i) ) {
$("#status").val("Unknown error");
return 0;
}
var rq = "copy_kml.php?proto="+res_arr[i].ID+"&kml="+$("#input_fn").val();
getRequest(rq,copy_done);
}
function copy_done(msg){
$("#status").val(msg);
postRequest("GetRoutesAndKMLs", "");
}
function xml_create(arr) {
var result_str = "";
for (var i=0;i<arr.length;i++) {
var tmp_str = "";
for(key in arr[i]) {
tmp_str += XMLString_CreateNode("\t\t",key,arr[i][key]);
}
result_str += XMLString_Wrap("\t","node",tmp_str);
}
return XMLString_AddXMLHeader(result_str,"data");
}
function kml_create(arr) {
var result_str = "";
for (var i=0;i<arr.length;i++) {
result_str += ArrayToXMLString(arr[i],"\t","PhotoOverlay");
}
return XMLString_AddKMLHeader(result_str,"Document");
}
/*! -----------------------------------------------------------------------------**
*! FILE NAME : pano_mouse_events.js
*! DESCRIPTION: Handles mouse events in panorama viewer/editor
*! Copyright (C) 2011 Elphel, Inc.
*!
*! -----------------------------------------------------------------------------**
**
** this program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
**
*/
var fovY = 45;
var mouseDown = false;
var lastMouseX = null;
var lastMouseY = null;
var showArrows = true;
var arrowsVisible=[];
var arrowsXY=[];
var currentArrow= -2; // -1 - floating Eyesis
var shiftKey=false;
var ctrlKey=false;
var altKey=false;
var viewRotationMatrix = Matrix.I(4); // current view rotation matrix
var panoramaRotationMatrix = Matrix.I(4); // rotation matrix of the current panorama relative to the world
var previousPanoramaRotationMatrix; // rotation matrix of the current panorama relative to the world
function handleKeyUp(event) {
floatingEyesisHorizontal=true;
}
function handleMouseDown(event) {
shiftKey= event.shiftKey && !event.altKey && editEnabled;
ctrlKey= event.ctrlKey && !event.altKey && editEnabled;
altKey= event.altKey && editEnabled; // press with SHIFT to disable
floatingEyesisHorizontal= !altKey && !verticalEnabled;
// if (floatingEyesisHorizontal) currentArrow=-1; // if started moving with SHIFT then released/pressed mouse while shift is held - continue dragging that camera
//document.title="floatingEyesisXY[0]="+floatingEyesisXY[0]+" floatingEyesisXY[1]="+floatingEyesisXY[1]+" currentArrow="+currentArrow+" floatingEyesisDragging="+floatingEyesisDragging+" floatingEyesisHorizontal="+floatingEyesisHorizontal+" altKey="+altKey;
if (!editEnabled && !shiftKey && !ctrlKey && (currentArrow>=0)) { // all hyperjumps are disabled in edit mode. Maybe just need to ask for confirmation/save edits
clickedArrow(currentArrow);
return; // was no return here
}
// if (editEnabled && (currentArrow>0) && (floatingEyesisNum<0)) cloneEyesis(currentArrow); // copy current camera to pair (ghost/edit, show control fields)
if (editEnabled && (currentArrow>=0) && (floatingEyesisNum<0)) cloneEyesis(currentArrow); // copy current camera to pair (ghost/edit, show control fields)
floatingEyesisDragging=editEnabled && (currentArrow>=-1);
// if (editEnabled && (currentArrow>=-1) && shiftKey && ctrlKey) floatingEyesisHorizontal=true; // CNTRL+SHIFT, not to start SHIFT-move accidentally
// if (editEnabled && (currentArrow>=-1) && altKey) floatingEyesisHorizontal=true; // CNTRL+SHIFT, not to start SHIFT-move accidentally
mouseDown = true;
lastMouseX = event.clientX;
lastMouseY = event.clientY;
if (ctrlKey && !floatingEyesisDragging) {
var direction=azimuth + ((lastMouseX-gl.viewportWidth/2) /gl.viewportHeight*fovY);
direction=Math.round (10*direction)/10;
lockAxis(direction);
}
drawScene();
savedX=event.clientX;
savedY=event.clientY;
if (floatingEyesisDragging) {
floatingEyesisStart.angle=floatingEyesis.angle;
floatingEyesisStart.down=floatingEyesis.down;
floatingEyesisStart.distance=floatingEyesis.distance; // always>0?
} else if (!shiftKey && !ctrlKey) {
savedA=azimuth;
savedE=elevation;
} else {
savedH=map[0].heading;
savedT=map[0].tilt;
savedR=map[0].roll;
}
ortoDir=-1;
}
function clickedArrow(num) {
// alert ("clickedArrow("+num+")");
// if (num==0) return; // do nothing if clicked self //try if it is OK
// var url=serverURL+"?kml="+settings.kml+"&href="+map[num+1].href+"&range="+settings.range;
var url=serverURL+"?kml="+settings.kml+"&href="+map[num].href+"&range="+settings.range;
if ((typeof(settings.proto)!="undefined") && (settings.proto!="")) url+="&proto="+settings.proto; // use this KML file as a prototype for kml= (copy to kml if kml does not exist)
if (settings.mask!="") url+="&mask="+settings.mask; // use second KML file to overwrite main KML file settings
if (settings.map!="") url+="&map="+settings.map; // specify if full map rebuild is needed (default - sequential) or if interpolation for "visibility=0" is needed
// if (settings.Visibility3d) url+="&v3d";
lastHeading=map[0].heading;// global
waitForPano=true;
document.body.style.cursor="wait";
requestKml(url,kmlGot);
return;
}
function clickedLabel(event,num) {
currentArrow=num;
handleMouseDown(event);
}
var azimuth=0;
var elevation=0;
function handleMouseUp(event) {
mouseDown = false;
mouseDownPlan=false;
}
function handleMouseMove(event) {
if (handlePlanMouseMove(event)) return; // captured by handlePlanMouseMove()
var newX = event.clientX;
var newY = event.clientY;
var needRedrawArrows=false;
var overCanvas=(newX>=0) && (newY>=0) && (newX<gl.viewportWidth) && (newY<gl.viewportHeight);
if (showArrows!=(overCanvas || editEnabled)) {
showArrows=(overCanvas || editEnabled);
needRedrawArrows=true;
}
if (!overCanvas) {
document.body.style.cursor="default";
if (needRedrawArrows) setTimeout ("drawScene()", 50 ); // That works! For some reason Chrome (sometimes) fails to show arrows when cursor is moved to over canvas from outside
return;
}
if (!mouseDown) {
//document.title="handleMouseMove: currentArrow="+currentArrow;
detectOverArrow(newX,newY);
if (waitForPano) document.body.style.cursor="wait";
else if (currentArrow>=-1) document.body.style.cursor="pointer";
else if (editEnabled && ((event.shiftKey==1) || (event.ctrlKey==1))) document.body.style.cursor="crosshair";
else document.body.style.cursor="move";
lastMouseX=newX;
lastMouseY=newY;
if (needRedrawArrows) setTimeout ("drawScene()", 50 ); // That works! For some reason Chrome (sometimes) fails to show arrows when cursor is moved to over canvas from outside
return;
}
var deltaX = newX - lastMouseX;
var deltaY = newY - lastMouseY;
if (document.getElementById("idOrtho").checked) {
var dX0 = newX - savedX
var dY0 = newY - savedY;
var k=Math.sqrt((dX0*dX0+dY0*dY0)/ (orthoStep*orthoStep));
if (ortoDir<0) { // undefined yet - too small travel from the mousedown point
lastMouseX=savedX;
lastMouseY=savedY;
deltaX = newX - lastMouseX;
deltaY = newY - lastMouseY;
if (floatingEyesisDragging) {
floatingEyesis.angle=floatingEyesisStart.angle;
floatingEyesis.down=floatingEyesisStart.down;
floatingEyesis.distance=floatingEyesisStart.distance; // always>0?
} else if (!shiftKey && !ctrlKey) {
azimuth=savedA;
elevation=savedE;
} else {
map[0].heading=savedH;
map[0].tilt=savedT;
map[0].roll=savedR;
}
if (deltaX*deltaX>deltaY*deltaY) deltaY=0;
else deltaX=0;
if (k>1.0) ortoDir=(deltaY*deltaY>deltaX*deltaX)?1:0;
} else { // direction was set, maybe need to change
if (k>1.0) { // rope is tight, move "weight" towards the current mouse pointer
savedX=Math.round(savedX+dX0*(k-1)/k);
savedY=Math.round(savedY+dY0*(k-1)/k);
ortoDir=(dX0*dX0>dY0*dY0)?0:1; // only change direction if the "rope is tight"
}
if (ortoDir>0) deltaX=0;
else deltaY=0;
}
}
if (floatingEyesisDragging) {
document.body.style.cursor="move";
floatingEyesis.angle=floatingEyesis.angle+(-deltaX /gl.viewportHeight*fovY);
// while (floatingEyesis.angle<0) floatingEyesis.angle+=360;
// while (floatingEyesis.angle>=360)floatingEyesis.angle-=360;
while (-floatingEyesis.angle<0) floatingEyesis.angle-=360;
while (-floatingEyesis.angle>=360) floatingEyesis.angle+=360;
if (floatingEyesisHorizontal) { // move azimuth/distance (horizontal plane)
floatingEyesis.distance=floatingEyesis.distance-Math.abs(floatingEyesis.distance)* Math.sin(Math.PI/180*deltaY /gl.viewportHeight*fovY);
} else { // move azimuth/elevation (vertical plane)
floatingEyesis.down=floatingEyesis.down+Math.abs(floatingEyesis.distance)* Math.sin(Math.PI/180*deltaY /gl.viewportHeight*fovY);
}
updatePositionControlsAndMap();
} else if (!shiftKey && !ctrlKey) {
document.body.style.cursor="move";
azimuth=azimuth+(-deltaX /gl.viewportHeight*fovY);
elevation=elevation+(-deltaY/gl.viewportHeight*fovY);
while (azimuth<0)azimuth+=360;
while (azimuth>=360)azimuth-=360;
if (elevation>90) elevation=90;
if (elevation<-90) elevation=-90;
if (showInfo) showInformation();
// var newRotationMatrix = createRotationMatrix(elevation, [1, 0, 0]);
// viewRotationMatrix = newRotationMatrix.x(createRotationMatrix(azimuth, [0, 1, 0]));
} else if (shiftKey) {
document.body.style.cursor="crosshair";
map[0].heading=map[0].heading+(deltaX /gl.viewportHeight*fovY);
while (map[0].heading<0)map[0].heading+=360;
while (map[0].heading>=360)map[0].heading-=360;
var ang=deltaY/gl.viewportHeight*fovY;
var axisDir;
if (!directionIsLocked) { // rotate around horizontal axis perpendicular to view
axisDir=(map[0].heading-azimuth)*Math.PI/180;
map[0].tilt-=ang*Math.cos(axisDir);
map[0].roll+=ang*Math.sin(axisDir);///
} else { // rotate around horizontal axis at lockedDirection
axisDir=(map[0].heading-(lockedDirection+90))*Math.PI/180;
var mouseDir=azimuth + ((newX-gl.viewportWidth/2) /gl.viewportHeight*fovY);
ang/=Math.sin((mouseDir-lockedDirection)*Math.PI/180);
map[0].tilt-=ang*Math.cos(axisDir);
map[0].roll+=ang*Math.sin(axisDir); ///
}
if (map[0].tilt>(90+maxPanoTilt)) map[0].tilt=(90+maxPanoTilt);
if (map[0].tilt<(90-maxPanoTilt)) map[0].tilt=(90-maxPanoTilt);
if (map[0].roll> maxPanoTilt) map[0].roll=maxPanoTilt;
if (map[0].roll<-maxPanoTilt) map[0].roll=-maxPanoTilt;
recalcHTR();
showInformation();
}
lastMouseX = newX
lastMouseY = newY;
drawScene();
}
function detectOverArrow(x,y) {
var minRadius2= arrowRadius*arrowRadius;
currentArrow= -2; // none, -1 - floating Eyesis, >=0 - regular eyesis or arrow
var minDist=-1; // invalid
var dx,dy,r2;
if (floatingEyesisNum<0) {
for (var i =1; i<arrowsVisible.length; i++) if ((i<arrows.length) && arrowsVisible[i] && (!editEnabled || (arrows[i].type=='c') ) ){ // arrowsXY[i].distance<0 means Eyesis, not arrow
dx=x-arrowsXY[i].x;
dy=y-arrowsXY[i].y;
r2=dx*dx+dy*dy;
if ((r2<minRadius2) && ((minDist<0) || (minDist>Math.abs(arrows[i].distance)))) {
currentArrow=i;
if (settings.closestIn2d) minRadius2=r2;
else minDist=Math.abs(arrows[i].distance);
}
}
} else if (floatingEyesisVisible){
dx=x-floatingEyesisXY[0];
dy=y-floatingEyesisXY[1];
r2=dx*dx+dy*dy;
// if ((r2<minRadius2) || floatingEyesisHorizontal) {
if (r2<minRadius2) {
currentArrow=-1;
}
//document.title="floatingEyesisXY[0]="+floatingEyesisXY[0]+" floatingEyesisXY[1]="+floatingEyesisXY[1]+" dx="+dx+" dy="+dy+" currentArrow="+currentArrow+" floatingEyesisDragging="+floatingEyesisDragging+" floatingEyesisHorizontal="+floatingEyesisHorizontal;
}
}
function wheelEvent(event){
var delta = 0;
if (!event) event = window.event; // IE
if (event.wheelDelta) { //IE+Opera
delta = event.wheelDelta/120;
if (window.opera) delta = -delta;
} else if (event.detail) { // Mozilla
delta = -event.detail/3;
}
if (delta)
handleWheel(delta);
if (event.preventDefault)
event.preventDefault();
event.returnValue = false;
shiftKey= (event.shiftKey==1);
}
function handleWheel(delta) {
//console.log("HandleWheel: fovY: "+fovY);
fovY=fovY*Math.pow(fovK,-delta);
if ((fovY<fovYMin) && !shiftKey) fovY=fovYMin; // with SHIFT, any zoom is allowed
if ((fovY>fovYMax) && !shiftKey) fovY=fovYMax; // with SHIFT, any zoom is allowed
update_fovY();
if (currentTextureHeight>0) {
currentZoom=Math.round(1000*180*gl.viewportHeight/currentTextureHeight/fovY)/1000;
showZoom();
}
drawScene();
}
function addEvent(obj, evt, fn) {
if (obj.addEventListener) {
obj.addEventListener(evt, fn, false);
}
else if (obj.attachEvent) {
obj.attachEvent("on" + evt, fn);
}
}
addEvent(window,"load",function(e) {
addEvent(document, "mouseout", function(e) {
e = e ? e : window.event;
var from = e.relatedTarget || e.toElement;
if (!from || from.nodeName == "HTML") {
// stop your drag event here
// for now we can just use an alert
if (showArrows && !editEnabled) {
showArrows=false;
drawScene();
}
document.body.style.cursor="default";
//document.title+=">"+showArrows;
}
});
});
html {
font-family:"Times New Roman", Times, serif;
}
.small_text {
font-size: 10px;
}
#idTopRightCorner {
position: absolute;
top: 5px;
right: 5px;
overflow: auto;
}
#idHeading, #idTilt, #idRoll {
width: 50px;
}
#idDialogs, #idHelpDialog {
position: absolute;
top: 30px;
right: 5px;
z-index: 1000;
}
#idViewsDialog {
padding : 2px 5px 2px 5px;
margin-top: 3px;
margin-bottom: 5px;
}
#idSettings, #idHelp, #idViews {
/*display: inline;*/
float: left;
/*background: rgba(200,200,200,0.8);*/
padding : 2px 5px 2px 5px;
margin: 0px 2px 2px 0px;
}
#idSettings:hover, #idHelp:hover, #idViews:hover {
color: white;
cursor: pointer;
}
#idSettings:active, #idHelp:active {
background: -webkit-gradient(linear, left top, left bottom, from(rgba(255,255,255,0.5)), to(rgba(225,225,225,0.8))); /* for webkit browsers */
background: -moz-linear-gradient(top, rgba(255,255,255,0.5), rgba(255,255,255,0.8)); /* for firefox 3.6+ */
-moz-box-shadow: 0px 0px 0px black;
-webkit-box-shadow: 0px 0px 0px black;
box-shadow: 0px 0px 0px black;
}
#idSettingsDialog {
/* width: 450px;*/
/* height: 520px;*/
padding: 5px;
margin-top: 3px;
overflow: auto;
}
#idSettingsDialogNumTextures {
width: 40px;
}
#idSettingsDialogOkButton,#idSettingsDialogCancelButton {
float:left;
padding: 2px 5px 2px 5px;
font-size: 14px;
}
#idSettingsDialogOkButton:hover,#idSettingsDialogCancelButton:hover {
color: white;
cursor: pointer;
}
#idSettingsDialogOkButton:active,#idSettingsDialogCancelButton:active {
border: 0px;
background: -webkit-gradient(linear, left top, left bottom, from(rgba(210,210,210,1)), to(rgba(180,180,180,1))); /* for webkit browsers */
background: -moz-linear-gradient(top, rgba(180,180,180,1), rgba(210,210,210,1)); /* for firefox 3.6+ */
}
.gradient {
/*background: rgba(255,255,255,0.7);*/
background: -webkit-gradient(linear, left top, left bottom, from(rgba(255,255,255,0.9)), to(rgba(225,225,225,0.6))); /* for webkit browsers */
background: -moz-linear-gradient(top, rgba(255,255,255,0.9), rgba(255,255,255,0.6)); /* for firefox 3.6+ */
-moz-box-shadow: 2px 2px 2px black;
-webkit-box-shadow: 2px 2px 2px black;
box-shadow: 2px 2px 2px black;
-moz-border-radius:3px;
-webkit-border-radius:3px;
border-radius:3px;
}
.input_field {
border: 1px solid black;
-moz-border-radius:3px;
-webkit-border-radius:3px;
border-radius:3px;
padding: 2px 1px 2px 1px;
}
.input_field:disabled {
color: black;
}
.button {
font-size: 12px;
border: 0px;
background: -webkit-gradient(linear, left top, left bottom, from(rgba(180,180,180,1)), to(rgba(210,210,210,1))); /* for webkit browsers */
background: -moz-linear-gradient(top, rgba(210,210,210,1), rgba(180,180,180,1)); /* for firefox 3.6+ */
-moz-box-shadow: 2px 2px 2px black;
-webkit-box-shadow: 2px 2px 2px black;
box-shadow: 2px 2px 2px black;
-moz-border-radius:3px;
-webkit-border-radius:3px;
border-radius:3px;
}
.button:hover {
color: white;
cursor: pointer;
}
.button:active {
border: 0px;
background: -webkit-gradient(linear, left top, left bottom, from(rgba(210,210,210,1)), to(rgba(180,180,180,1))); /* for webkit browsers */
background: -moz-linear-gradient(top, rgba(180,180,180,1), rgba(210,210,210,1)); /* for firefox 3.6+ */
}
.button:disabled {
-moz-box-shadow: 1px 1px 1px black;
-webkit-box-shadow: 1px 1px 1px black;
box-shadow: 1px 1px 1px black;
background: -webkit-gradient(linear, left top, left bottom, from(rgba(180,180,180,1)), to(rgba(210,210,210,1))); /* for webkit browsers */
background: -moz-linear-gradient(top, rgba(210,210,210,1), rgba(180,180,180,1)); /* for firefox 3.6+ */
}
#IdSeeThroughDiv {
margin: 5px;
}
#seeThroughInput {
width: 35px;
}
/*see through slider*/
#seeThroughSlider {
width: 10px;
margin: 5px;
}
#seeThroughSlider .ui-slider-handle {
left: -3px;
background: white;
border-color: rgba(0,0,0,1);
width: 15px;
height: 15px;
}
#idSettingsNumTextures, #idSettingsRange, #idSettingsAsCamera, #idSettingsSeeThrough, #idSettingsTransitionTime, #idSettingsTransitionSteps, #idSettingsDotSize {
width: 40px;
text-align: right;
}
#idSettingsThisColor, #idSettingsColor, #idSettingsSelectedColor, #idSettingsGhostColor, #idSettingsInvisibleColor {
width: 65px;
}
#idSettingsMap {
width: 70px;
}
#idSettingsStart {
width: 300px;
}
.small_square {
width: 19px;
height: 19px;
border: 1px solid black;
-moz-border-radius:3px;
-webkit-border-radius:3px;
border-radius:3px;
}
#idPlanView {
-moz-box-shadow: 2px 2px 2px black;
-webkit-box-shadow: 2px 2px 2px black;
box-shadow: 2px 2px 2px black;
-moz-border-radius:3px;
-webkit-border-radius:3px;
border-radius:3px;
}
#idViewAzimuth, #idViewElevation {
width: 60px;
}
#idInfo{
position: absolute;
bottom: 3px;
left: 3px;
padding : 2px 4px 2px 4px;
overflow: auto;
}
#idInfo_toggle {
width: 67px;
padding : 2px 5px 2px 5px;
/*display: inline;*/
float: left;
}
#idInfo_toggle:hover {
color: white;
cursor: pointer;
}
#idPermanentLink_div {
/*display: inline;*/
float: left;
padding: 2px 5px 2px 5px;
}
#idHelpDialog {
padding: 2px 5px 2px 5px;
margin-top: 3px;
}
#error_no_webgl{
-moz-box-shadow: 2px 2px 6px black;
-webkit-box-shadow: 2px 2px 6px black;
box-shadow: 2px 2px 6px black;
}
#kml_proto_list {
position: absolute;
top: 30px;
left: 140px;
width: 300px;
height: 20px;
z-index: 1002;
}
#kml_mask_list {
position: absolute;
top: 78px;
left: 140px;
width: 300px;
height: 20px;
z-index: 1001;
}
#idSettingsKml{
width: 300px;
position: absolute;
left: 140px;
top: 54px;
height: 22px;
}
#idSettingsMap{
width: 300px;
position: absolute;
left: 140px;
top: 102px;
height: 22px;
}
\ No newline at end of file
/*
*! -----------------------------------------------------------------------------**
*! FILE NAME : plan_view.js
*! REVISION : 1.0
*! DESCRIPTION: Handles drawing, rmoving/resizing and capturing mouse events
*! for the plan view
*! Copyright (C) 2011 Elphel, Inc.
*!
*! -----------------------------------------------------------------------------**
*! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*!
*! It means that the program's users have the four essential freedoms:
*!
*! * The freedom to run the program, for any purpose (freedom 0).
*! * The freedom to study how the program works, and change it to make it do what you wish (freedom 1).
*! Access to the source code is a precondition for this.
*! * The freedom to redistribute copies so you can help your neighbor (freedom 2).
*! * The freedom to distribute copies of your modified versions to others (freedom 3).
*!
*! By doing this you can give the whole community a chance to benefit from your changes.
*! Access to the source code is a precondition for this.
*! -----------------------------------------------------------------------------**
*/
//var fovYMaxPlan=fovYMax; // adjust separately? fovY when plan is the 2*settings.range x 2*settings.range square
var fovYMaxPlan; // adjust separately? fovY when plan is the 2*settings.range x 2*settings.range square
var mouseDownPlan=false;
var mouseDownPlanMove=false; // valid only with mouseDownPlan
var mouseDownPlanResize=false; // valid only with mouseDownPlan
function handlePlanMouseDown(event,which,visibility){ // -2 - none, -1 - selected, 0 - center, >0 - arrow+1
// lastMouseX = this.event.clientX; //
// lastMouseY = this.event.clientY;
if ((which!=-2) && !visibility && !event.shiftKey && !event.ctrlKey) return; // invisible cameras are only dragged with SHIFT or CNTRL
lastMouseX = event.clientX; //
lastMouseY = event.clientY;
//document.title=event.clientX+":"+event.clientY;
var size= parseInt(document.getElementById("idPlanView").style.width);
var top= parseInt(document.getElementById("idPlanView").style.top);
var left= parseInt(document.getElementById("idPlanView").style.left);
mouseDownPlanMove=false; // valid only with mouseDownPlan
mouseDownPlanResize=false; // valid only with mouseDownPlan
var moveHot=0.1*size;
// document.title=which;
if (which<-1) {
if (((lastMouseX-left)<moveHot) && ((lastMouseY-top)<moveHot)) {
mouseDownPlanMove=true;
// document.title+="++move";
} else if (((lastMouseX-left)>=(size-moveHot)) && ((lastMouseY-top)>=(size-moveHot))) {
mouseDownPlanResize=true;
// document.title+="++resize";
} else {
// document.title+="++inside";
// close to a dot?
}
} else {
// document.title=which;
// alert ("dot number "+which);
currentArrow=which;
// handleMouseDown(this.event);
handleMouseDown(event);
mouseDown=false; // will not drag webgl view
}
//alert ("lastMouseX="+lastMouseX+"\nlastMouseY="+lastMouseY);
mouseDownPlan=true;
}
function handlePlanMouseMove(event) { // returns true if processed here, false - continue other mousemove
if (mouseDown) return false ; // does not belong here
// document.title="mouseDownPlanMove="+mouseDownPlanMove+" mouseDownPlanResize="+mouseDownPlanResize;
var size= parseInt(document.getElementById("idPlanView").style.width);
var top= parseInt(document.getElementById("idPlanView").style.top);
var left= parseInt(document.getElementById("idPlanView").style.left);
var moveHot=0.1*size;
var newX = event.clientX;
var newY = event.clientY;
if (mouseDownPlan) {
if (mouseDownPlanMove) {
// document.title+="--move";
movePlanView (newX-lastMouseX,newY-lastMouseY);
} else if (mouseDownPlanResize) {
// document.title+="--resize";
resizePlanView(newX-lastMouseX,newY-lastMouseY);
} else {
//TODO: move camera
// document.title="--inside";
if (floatingEyesisNum>=0) { // move selected camera, no matter where clicked
var dx=(newX-lastMouseX)/(size/2)*settings.range/fovYMaxPlan*fovY; // in meters, positive in view azimuth+90
var dy=(newY-lastMouseY)/(size/2)*settings.range/fovYMaxPlan*fovY; // in meters, positive in view azimuth+1807334
var a=Math.PI/180*(azimuth);
var sina=Math.sin(a);
var cosa=Math.cos(a);
var dNorth=-dx*sina-dy*cosa;
var dEast= dx*cosa-dy*sina;
var targeta=Math.PI/180*(-floatingEyesis.angle);
var dist= Math.abs(floatingEyesis.distance);
var north=dist*Math.cos(targeta);
var east=dist*Math.sin(targeta);
//document.title="f0="+floatingEyesis.angle+" f2="+floatingEyesis.distance;
//document.title+="dx="+Math.round(dx*1000)/1000+" dy="+Math.round(dy*1000)/1000+" n="+Math.round(north*1000)/1000+" e="+Math.round(east*1000)/1000+" ta="+Math.round(targeta*10)/10+" d="+Math.round(dist*1000)/1000;
north+=dNorth;
east+=dEast;
dist=Math.sqrt(north*north+east*east);
a=180/Math.PI*Math.atan2(east,north); // in degrees, -floatingEyesis.angle
//document.title+=" n="+Math.round(north*1000)/1000+" e="+Math.round(east*1000)/1000+" a="+Math.round(a*10)/10+" d="+Math.round(dist*1000)/1000;
floatingEyesis.angle=-a;
floatingEyesis.distance=dist;
//document.title=" f0="+floatingEyesis.angle+" f2="+floatingEyesis.distance;
updatePositionControlsAndMap();
drawScene();
}
}
} else {
var x=newX-left;
var y=newY-top;
if ((x<0) || (x>=size) || (y<0) || (y>=size)) return false; // mouse over, but not over plan
// document.title+=" x="+x+" y="+y;
if ((x<moveHot) && (y<moveHot)) document.body.style.cursor="move";
else if ((x>=(size-moveHot)) && (y>=(size-moveHot))) document.body.style.cursor="nw-resize";
else document.body.style.cursor="default";
//document.body.style.cursor="pointer";
}
lastMouseX = newX;
lastMouseY = newY;
return true;
}
// if (editEnabled && (currentArrow>0) && (floatingEyesisNum<0)) cloneEyesis(currentArrow); // copy current camera to pair (ghost/edit, show control fields)
function movePlanView(dx,dy){
var top= parseInt(document.getElementById("idPlanView").style.top)+dy;
var left= parseInt(document.getElementById("idPlanView").style.left)+dx;
document.getElementById("idPlanView").style.top= top+"px";
document.getElementById("idPlanView").style.left=left+"px";
}
function resizePlanView(dx,dy){
var minPlanViewSize=100;
var width= parseInt(document.getElementById("idPlanView").style.width)+dx;
var height= parseInt(document.getElementById("idPlanView").style.height)+dy;
if (width>height) height=width;
else width=height;
if (width<minPlanViewSize) width= minPlanViewSize;
if (height<minPlanViewSize) height=minPlanViewSize;
document.getElementById("idPlanView").style.width= width+"px";
document.getElementById("idPlanView").style.height=height+"px";
drawScene();
}
function showPlanView(show){
if (typeof(fovYMaxPlan)=='undefined')fovYMaxPlan=fovYMax;
if (show) {
var size= parseInt(document.getElementById("idPlanView").style.width);
var top= parseInt(document.getElementById("idPlanView").style.top);
var left= parseInt(document.getElementById("idPlanView").style.left);
var innerHTML=""; // TODO: will it be faster if the divs will be just
var x,y,dist,a;
var offs=Math.round((settings.planDotSize-1)/2);
//if (document.getElementById("idPlanView").style.display=="none") alert ("size="+size+"\ntop="+top+"\nleft="+left);
// TODO: add this point
for (var i=(floatingEyesisNum>=0)?-1:0;i<arrows.length;i++) if ((i<0) || (arrows[i].type=='c')){ // 0 - same
// arrows[0] - azimuth
// arrows[2]>0 = arrow, <0 camera, abs(arrows[2] - distance (meters)
//floatingEyesisNum
var i0=(i<0)?floatingEyesisNum:i;
var visibility=settings.markVisibility3d?(map[i0].open!==false):(map[i0].visibility!==false);
var color=(i<0)?settings.planColorSelected:((i==floatingEyesisNum)? settings.planColorGhost:((i==0)?settings.planThisColor:(visibility?settings.planColor:settings.planColorInvisible)));
var ts="";
/*
if (typeof(map[i0].description)!='undefined') ts+=' '+map[i0].description;
else if (typeof(map[i0].name)!='undefined') ts+=' '+map[i0].name;
*/
if (typeof(map[i0].name)!='undefined') ts+=map[i0].name+" - ";
if (typeof(map[i0].description)!='undefined') ts+=map[i0].description+" ";
ts+=map[i0].time.hour+":"+map[i0].time.minute+":"+Math.round(map[i0].time.second*10)/10;
if (i<0) {
dist=Math.abs(floatingEyesis.distance)/settings.range*fovYMaxPlan/fovY; // Fraction of half square side
a=Math.PI/180*(-floatingEyesis.angle-azimuth); // for some reason - negative
} else {
dist=Math.abs(arrows[i].distance)/settings.range*fovYMaxPlan/fovY; // Fraction of half square side
a=Math.PI/180*(-arrows[i].angle-azimuth);
}
x=Math.round(size/2*(1+dist*Math.sin(a)))-offs;
y=Math.round(size/2*(1-dist*Math.cos(a)))-offs;
var zindex=(i<0)?3:(map[i].visibility?2:1);
//if (document.getElementById("idPlanView").style.display=="none") alert ("dist="+dist+"\nx="+x+"\ny="+y);
if ((x>=0) && (y>=0) && (x<(size-settings.planDotSize)) && (y<(size-settings.planDotSize))) {
innerHTML+='<div id="idPlanViewPoint'+(i)+'" title="'+ts+
'" style="position:absolute;width:'+settings.planDotSize+'px;height:'+settings.planDotSize+'px;top:'+y+'px;left:'+x+'px;'+
'-moz-border-radius:'+(settings.planDotSize/2)+'px;'+
'-webkit-border-radius:'+(settings.planDotSize/2)+'px;'+
'border-radius:'+(settings.planDotSize/2)+'px;'+
'cursor:pointer;'+
'background-color:'+color+';z-index:'+zindex+';" onmousedown="handlePlanMouseDown(event,'+i+','+((i<0) || map[i].visibility || settings.markVisibility3d)+')">&nbsp;</div>';
//onmousedown="handlePlanMouseDown(-2);
}
}
//TODO: add selected
document.getElementById("idPlanView").innerHTML=innerHTML;
//if (document.getElementById("idPlanView").style.display=="none") alert (document.getElementById("idPlanView").innerHTML);
document.getElementById("idPlanView").style.display="block";
} else {
document.getElementById("idPlanView").style.display="none";
}
}
/*
*! -----------------------------------------------------------------------------**
*! FILE NAME : seethrough_slider.js
*! REVISION : 1.0
*! DESCRIPTION: slider for viewing both textures in the edit mode
*! Copyright (C) 2011 Elphel, Inc.
*!
*! -----------------------------------------------------------------------------**
*! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*!
*! It means that the program's users have the four essential freedoms:
*!
*! * The freedom to run the program, for any purpose (freedom 0).
*! * The freedom to study how the program works, and change it to make it do what you wish (freedom 1).
*! Access to the source code is a precondition for this.
*! * The freedom to redistribute copies so you can help your neighbor (freedom 2).
*! * The freedom to distribute copies of your modified versions to others (freedom 3).
*!
*! By doing this you can give the whole community a chance to benefit from your changes.
*! Access to the source code is a precondition for this.
*! -----------------------------------------------------------------------------**
*/
$(function() {
$( "#seeThroughSlider" ).slider({
orientation: "vertical",
range: "min",
min: 0,
max: 99,
value: 50,
slide: function( event, ui ) {
$( "#seeThroughInput" ).val( ui.value/100 );
$( "#seeThroughInput" ).change();
}
});
$("#seeThroughInput").change(function(e){
settings.seethrough = $("#seeThroughInput").val();
drawScene();
//alert(settings.seethrough);
});
});
\ No newline at end of file
/*
*! -----------------------------------------------------------------------------**
*! FILE NAME : settings_dialog.js
*! REVISION : 1.0
*! DESCRIPTION: Settings menu
*! Copyright (C) 2011 Elphel, Inc.
*!
*! -----------------------------------------------------------------------------**
*! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*!
*! It means that the program's users have the four essential freedoms:
*!
*! * The freedom to run the program, for any purpose (freedom 0).
*! * The freedom to study how the program works, and change it to make it do what you wish (freedom 1).
*! Access to the source code is a precondition for this.
*! * The freedom to redistribute copies so you can help your neighbor (freedom 2).
*! * The freedom to distribute copies of your modified versions to others (freedom 3).
*!
*! By doing this you can give the whole community a chance to benefit from your changes.
*! Access to the source code is a precondition for this.
*! -----------------------------------------------------------------------------**
*/
var idSettingsDialog_flag = false;
$(function() {
$("#idInfo_toggle").click(function(e){
$("#idInfo_table").toggle();
if ($("#idInfo_toggle").html()=="hide info") $("#idInfo_toggle").html("show info");
else $("#idInfo_toggle").html("hide info");
});
$("#idInfo_toggle").click();
$("#idSettings").click(function(e){
$("#idViewsDialog").hide();
$("#idHelpDialog").hide();
$("#idSettingsDialog").toggle();
fillSettingsMenu();
});
$("#idSettingsDialogOkButton").click(function(e){
$("#idSettingsDialog").hide();
applySettingsMenu();
});
$("#idSettingsDialogCancelButton").click(function(e){
$("#idSettingsDialog").hide();
fillSettingsMenu();
});
// $("#idSettingsEdit").click(function(e){
// settings.edit = $(this).attr("checked");
// applyEditModeView();
// });
$("#idSettingsLabels").click(function(e){
settings.labels = $(this).attr("checked");
$("#idShowLabels").attr("checked",settings.labels);
drawScene();
});
$("#idSettingsClosestIn2D").click(function(e){
settings.closestIn2d = $(this).attr("checked");
});
$("#idSettingsKeepZoom").click(function(e){
settings.keepZoom = $(this).attr("checked");
});
$("#idSettingsSeeThrough").change(function(e){
if ($(this).val()<0) $(this).val(0);
if ($(this).val()>0.99) $(this).val(0.99);
settings.seethrough = $(this).val();
updateSeeThrough();
});
$("#idSettingsTransitionTime").change(function(e){
settings.transitionTime = $(this).val();
});
// $("#idSettingsTransitionSteps").change(function(e){
// settings.transitionSteps = $(this).val();
// });
$( "#idSettingsDotSize").change(function(){settings.planDotSize = $(this).val();drawScene();});
$( "#idSettingsThisColor").change(function(){settings.planThisColor = $(this).val(); $("#idSettingsThisColorSample").css({background:settings.planThisColor}); drawScene();});
$( "#idSettingsColor").change(function(){settings.planColor = $(this).val(); $("#idSettingsColorSample").css({background:settings.planColor}); drawScene();});
$( "#idSettingsSelectedColor").change(function(){settings.planColorSelected = $(this).val(); $("#idSettingsSelectedColorSample").css({background:settings.planSelectedColor}); drawScene();});
$( "#idSettingsGhostColor").change(function(){settings.planColorGhost = $(this).val(); $("#idSettingsGhostColorSample").css({background:settings.planGhostColor}); drawScene();});
$("#idSettingsInvisibleColor").change(function(){settings.planColorInvisible = $(this).val();$("#idSettingsinvisibleColorSample").css({background:settings.planColorInvisible});drawScene();});
$("#idViews").click(function(e){
$("#idSettingsDialog").hide();
$("#idHelpDialog").hide();
$("#idViewsDialog").toggle();
//fillSettingsMenu();
});
$("#idGMap_checkbox").click(function(e){
if (this.checked) $("#map_div").show();
else $("#map_div").hide();
});
$("#idOSMap_checkbox").click(function(e){
if (this.checked) $("#osmap_div").show();
else $("#osmap_div").hide();
});
$("#idHelp").click(function(e){
$("#idViewsDialog").hide();
$("#idSettingsDialog").hide();
$("#idHelpDialog").toggle();
//fillSettingsMenu();
});
$("#idSettingsView").click(function(e){
settings.view = this.checked;
clickedArrow(0);
});
});
var mapping_list= new Array("full","interpolate","all","full-all");
function fillSettingsMenu() {
//alert(kml_list.length+" vs "+kml_masks_list.length);
$("#kml_proto_list").html(list_html("kml_list",kml_list));
jquery_list('kml_proto_list',settings.proto);
//$("#idSettingsMask").val(settings.mask);
var tmp_list_value;
if ((typeof(settings.mask)=="undefined") || (settings.mask=="")) tmp_list_value='Choose a corresponding mask';
else tmp_list_value= settings.mask;
$("#kml_mask_list").html(list_html("kml_masks_list",kml_masks_list));
jquery_list('kml_mask_list',tmp_list_value);
$("#idSettingsEdit").attr("checked",settings.edit);
$("#idSettingsKml").val(settings.kml);
//$("#idSettingsProto").val(settings.proto);
//alert($('#kml_mask_list').val()+" "+settings.mask);
$("#idSettingsNumTextures").val(settings.numTextures);
$("#idSettingsStart").val(settings.start);
$("#idSettingsRange").val(settings.range);
$("#idSettingsAsCamera").val(settings.as_camera);
$("#idSettingsLabels").attr("checked", settings.labels);
$("#idSettingsClosestIn2D").attr("checked", settings.closestIn2d);
$("#idSettingsKeepZoom").attr("checked", settings.keepZoom);
$("#idSettingsSeeThrough").val(settings.seethrough);
$("#idSettingsTransitionTime").val(settings.transitionTime);
// $("#idSettingsTransitionSteps").val(settings.transitionSteps);
$("#idSettingsMap").val(settings.map);
var tmp_map_value;
if ((typeof(settings.map)=="undefined") || (settings.map=="")) tmp_map_value='Choose a map building method';
else tmp_map_value= settings.map;
$("#idSettingsMap").html(list_html("building_map_list",mapping_list));
jquery_list('idSettingsMap',tmp_map_value);
$("#idSettingsFollow").attr("checked", settings.follow);
// $("#idSettingsVisibility3d").attr("checked", settings.Visibility3d);
$("#idSettingsMarkVisibility3d").attr("checked", settings.markVisibility3d);
$("#idSettingsDotSize").val(settings.planDotSize);
$("#idSettingsThisColor").val(settings.planThisColor);
$("#idSettingsColor").val(settings.planColor);
$("#idSettingsSelectedColor").val(settings.planColorSelected);
$("#idSettingsGhostColor").val(settings.planColorGhost);
$("#idSettingsInvisibleColor").val(settings.planColorInvisible);
$("#idSettingsThisColorSample").css( {background:settings.planThisColor});
$("#idSettingsColorSample").css( {background:settings.planColor});
$("#idSettingsSelectedColorSample").css( {background:settings.planColorSelected});
$("#idSettingsGhostColorSample").css( {background:settings.planColorGhost});
$("#idSettingsInvisibleColorSample").css({background:settings.planColorInvisible});
};
function applySettingsMenu() {
var updateNodes = false;
if ((settings.proto!=$('#kml_proto_list').val())||(settings.kml!=$("#idSettingsKml").val())||(settings.mask!=$('#kml_mask_list').val())||(settings.start!=$("#idSettingsStart").val())||(settings.map!=$("#idSettingsMap").val())||(settings.range!=$("#idSettingsRange").val())||(settings.as_camera!=$("#idSettingsAsCamera").val())) {
updateNodes = true;
}
settings.edit = $("#idSettingsEdit").attr("checked");
settings.proto = $('#kml_proto_list').val(); //$("#idSettingsProto").val();
if (!typeof($("#idSettingsKml").val())||($("#idSettingsKml").val()=="")) settings.kml = settings.proto;
else settings.kml = $("#idSettingsKml").val();
if ($('#kml_mask_list').val()=='Choose a corresponding mask') settings.mask = "";
else settings.mask = $('#kml_mask_list').val();//$("#idSettingsMask").val();
//settings.numTextures = $("#idSettingsNumTextures").val();
settings.start = $("#idSettingsStart").val();
settings.range = $("#idSettingsRange").val();
settings.as_camera = $("#idSettingsAsCamera").val();
settings.labels = $("#idSettingsLabels").attr("checked");
settings.closestIn2d = $("#idSettingsClosestIn2D").attr("checked");
settings.keepZoom = $("#idSettingsKeepZoom").attr("checked");
settings.seethrough = $("#idSettingsSeeThrough").val();
settings.transitionTime = $("#idSettingsTransitionTime").val();
settings.follow = $("#idSettingsFollow").attr("checked");
// settings.Visibility3d = $("#idSettingsVisibility3d").attr("checked");
settings.markVisibility3d = $("#idSettingsMarkVisibility3d").attr("checked");
// settings.transitionSteps = $("#idSettingsTransitionSteps").val();
if ($("#idSettingsMap").val()=='Choose a map building method') settings.map = "";
else settings.map = $('#idSettingsMap').val();//$("#idSettingsMask").val();
//settings.map = $("#idSettingsMap").val();
settings.planDotSize = $("#idSettingsDotSize").val();
settings.planThisColor = $("#idSettingsThisColor").val();
settings.planColorSelected = $("#idSettingsSelectedColor").val();
settings.planColorGhost = $("#idSettingsGhostColor").val();
settings.planColorInvisible = $("#idSettingsInvisibleColor").val();
settings.view = $("#idSettingsView").attr("checked");
//settings.fovy = fovY;
//applySettings();
fillSettingsMenu();
//if (updateNodes) webGLInitialGetNodes();
if (updateNodes) {
initialize_maps_nowebgl();
}
else{
clickedArrow(0); // reload saved file
drawScene();
}
}
function createPermanentLink() {
var string = "<a href='";
string+= window.location.href.substr(0,window.location.href.lastIndexOf('?'));
string+="?kml="+settings.kml;
string+="&proto="+settings.proto;
if ((typeof(settings.view)!="undefined") && (settings.view)) string+="&view"; // force view only mode
string+="&ntxt="+settings.numTextures;
string+="&as_camera="+settings.as_camera;
string+="&start="+map[0].href.substr(map[0].href.lastIndexOf('/')+1);
string+="&range="+settings.range;
string+="&labels="+settings.labels;
string+="&keepzoom="+settings.keepZoom;
string+="&closest2d="+settings.closestIn2d;
string+="&seethrough="+settings.seethrough;
string+="&transition="+settings.transitionTime;
string+="&mask="+settings.mask;
if ((typeof(settings.map)!="undefined") && (settings.map!="")) string+="&map="+settings.map;
string+="&azimuth="+(Math.round(azimuth*10)/10);
string+="&elevation="+(Math.round(elevation*10)/10);
string+="&zoom="+(Math.round(currentZoom*1000)/1000);
string+="&follow="+settings.follow;
string+="&mv3d="+settings.markVisibility3d;
string+="&fovy="+settings.fovy;
string+="'>Permanent Link</a>";
$('#idPermanentLink_div').html(string);
}
function hideMenus() {
//$('#idDialogs').hide();
$('#idTopRightCorner').hide();
$('#idInfo').hide();
//$('#idPlanView').hide();
//$('#idLabels').hide();
}
function showMenus() {
//$('#idDialogs').hide();
$('#idTopRightCorner').show();
$('#idInfo').show();
}
var kml_list=Array();
var kml_masks_list=Array();
function get_filelist(){
$.ajax({
url: "filelist.php?type=kml",
type: "GET",
async:false,
success: function(xml){
list = xml.getElementsByTagName("f");
for(var i=0;i<list.length;i++) {
var tmp = list[i].firstChild.data;
if (tmp.lastIndexOf("mask")!=-1) {
kml_masks_list[kml_masks_list.length] = tmp;
}else{
kml_list[kml_list.length] = tmp;
}
}
}
});
}
function list_html(id,list){
var tmp = "<ul id="+id+">";
for(var i=0; i<list.length; i++) {
tmp = tmp + "<li>"+list[i]+"</li>";
}
tmp = tmp + "</ul>";
return tmp;
}
File added
/*!
*! Based on original work of National Oceanic and Atmospheric Administration, United States Department of Commerce
*! Description: This script can calculate the suns position based on date, time and latitude/longitude.
*! Original source at: http://www.srrb.noaa.gov/highlights/sunrise/azel.html
*! This version uses positive longitude for East, negative - for West
-----------------------------------------------------------------------------**
*! Copyright (C) 2011 Elphel, Inc.
*!
*! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*!
*! It means that the program's users have the four essential freedoms:
*!
*! * The freedom to run the program, for any purpose (freedom 0).
*! * The freedom to study how the program works, and change it to make it do what you wish (freedom 1). Access to the source code is a precondition for this.
*! * The freedom to redistribute copies so you can help your neighbor (freedom 2).
*! * The freedom to distribute copies of your modified versions to others (freedom 3).
*!
*! By doing this you can give the whole community a chance to benefit from your changes. Access to the source code is a precondition for this.
-----------------------------------------------------------------------------**/
//***********************************************************************/
//* Name: calcJD */
//* Type: Function */
//* Purpose: Julian day from calendar day */
//* Arguments: */
//* year : 4 digit year */
//* month: January = 1 */
//* day : 1 - 31 */
//* Return value: */
//* The Julian day corresponding to the date */
//* Note: */
//* Number is returned for start of day. Fractional days should be */
//* added later. */
//* Modified so the East longitude is positive!
//* http://www.srrb.noaa.gov/highlights/sunrise/azel.html */
//***********************************************************************/
function calcJD(year, month, day)
{
if (month <= 2) {
year -= 1;
month += 12;
}
var A = Math.floor(year/100);
var B = 2 - A + Math.floor(A/4);
var JD = Math.floor(365.25*(year + 4716)) + Math.floor(30.6001*(month+1)) + day + B - 1524.5;
return JD;
}
//***********************************************************************/
//* Name: calcTimeJulianCent */
//* Type: Function */
//* Purpose: convert Julian Day to centuries since J2000.0. */
//* Arguments: */
//* jd : the Julian Day to convert */
//* Return value: */
//* the T value corresponding to the Julian Day */
//***********************************************************************/
function calcTimeJulianCent(jd)
{
var T = (jd - 2451545.0)/36525.0;
return T;
}
//***********************************************************************/
//* Name: calGeomMeanLongSun */
//* Type: Function */
//* Purpose: calculate the Geometric Mean Longitude of the Sun */
//* Arguments: */
//* t : number of Julian centuries since J2000.0 */
//* Return value: */
//* the Geometric Mean Longitude of the Sun in degrees */
//***********************************************************************/
function calcGeomMeanLongSun(t)
{
var L0 = 280.46646 + t * (36000.76983 + 0.0003032 * t);
while(L0 > 360.0)
{
L0 -= 360.0;
}
while(L0 < 0.0)
{
L0 += 360.0;
}
return L0; // in degrees
}
//***********************************************************************/
//* Name: calGeomAnomalySun */
//* Type: Function */
//* Purpose: calculate the Geometric Mean Anomaly of the Sun */
//* Arguments: */
//* t : number of Julian centuries since J2000.0 */
//* Return value: */
//* the Geometric Mean Anomaly of the Sun in degrees */
//***********************************************************************/
function calcGeomMeanAnomalySun(t)
{
var M = 357.52911 + t * (35999.05029 - 0.0001537 * t);
return M; // in degrees
}
//***********************************************************************/
//* Name: calcEccentricityEarthOrbit */
//* Type: Function */
//* Purpose: calculate the eccentricity of earth's orbit */
//* Arguments: */
//* t : number of Julian centuries since J2000.0 */
//* Return value: */
//* the unitless eccentricity */
//***********************************************************************/
function calcEccentricityEarthOrbit(t)
{
var e = 0.016708634 - t * (0.000042037 + 0.0000001267 * t);
return e; // unitless
}
//***********************************************************************/
//* Name: calGeomMeanLongSun */
//* Type: Function */
//* Purpose: calculate the Geometric Mean Longitude of the Sun */
//* Arguments: */
//* t : number of Julian centuries since J2000.0 */
//* Return value: */
//* the Geometric Mean Longitude of the Sun in degrees */
//***********************************************************************/
function calcGeomMeanLongSun(t)
{
var L0 = 280.46646 + t * (36000.76983 + 0.0003032 * t);
while(L0 > 360.0)
{
L0 -= 360.0;
}
while(L0 < 0.0)
{
L0 += 360.0;
}
return L0; // in degrees
}
//***********************************************************************/
//* Name: calGeomAnomalySun */
//* Type: Function */
//* Purpose: calculate the Geometric Mean Anomaly of the Sun */
//* Arguments: */
//* t : number of Julian centuries since J2000.0 */
//* Return value: */
//* the Geometric Mean Anomaly of the Sun in degrees */
//***********************************************************************/
function calcGeomMeanAnomalySun(t)
{
var M = 357.52911 + t * (35999.05029 - 0.0001537 * t);
return M; // in degrees
}
//***********************************************************************/
//* Name: calcEccentricityEarthOrbit */
//* Type: Function */
//* Purpose: calculate the eccentricity of earth's orbit */
//* Arguments: */
//* t : number of Julian centuries since J2000.0 */
//* Return value: */
//* the unitless eccentricity */
//***********************************************************************/
function calcEccentricityEarthOrbit(t)
{
var e = 0.016708634 - t * (0.000042037 + 0.0000001267 * t);
return e; // unitless
}
//***********************************************************************/
//* Name: calcSunEqOfCenter */
//* Type: Function */
//* Purpose: calculate the equation of center for the sun */
//* Arguments: */
//* t : number of Julian centuries since J2000.0 */
//* Return value: */
//* in degrees */
//***********************************************************************/
function calcSunEqOfCenter(t)
{
var m = calcGeomMeanAnomalySun(t);
var mrad = degToRad(m);
var sinm = Math.sin(mrad);
var sin2m = Math.sin(mrad+mrad);
var sin3m = Math.sin(mrad+mrad+mrad);
var C = sinm * (1.914602 - t * (0.004817 + 0.000014 * t)) + sin2m * (0.019993 - 0.000101 * t) + sin3m * 0.000289;
return C; // in degrees
}
//***********************************************************************/
//* Name: calcSunTrueLong */
//* Type: Function */
//* Purpose: calculate the true longitude of the sun */
//* Arguments: */
//* t : number of Julian centuries since J2000.0 */
//* Return value: */
//* sun's true longitude in degrees */
//***********************************************************************/
function calcSunTrueLong(t)
{
var l0 = calcGeomMeanLongSun(t);
var c = calcSunEqOfCenter(t);
var O = l0 + c;
return O; // in degrees
}
//***********************************************************************/
//* Name: calcSunTrueAnomaly */
//* Type: Function */
//* Purpose: calculate the true anamoly of the sun */
//* Arguments: */
//* t : number of Julian centuries since J2000.0 */
//* Return value: */
//* sun's true anamoly in degrees */
//***********************************************************************/
function calcSunTrueAnomaly(t)
{
var m = calcGeomMeanAnomalySun(t);
var c = calcSunEqOfCenter(t);
var v = m + c;
return v; // in degrees
}
//***********************************************************************/
//* Name: calcSunRadVector */
//* Type: Function */
//* Purpose: calculate the distance to the sun in AU */
//* Arguments: */
//* t : number of Julian centuries since J2000.0 */
//* Return value: */
//* sun radius vector in AUs */
//***********************************************************************/
function calcSunRadVector(t)
{
var v = calcSunTrueAnomaly(t);
var e = calcEccentricityEarthOrbit(t);
var R = (1.000001018 * (1 - e * e)) / (1 + e * Math.cos(degToRad(v)));
return R; // in AUs
}
//***********************************************************************/
//* Name: calcSunApparentLong */
//* Type: Function */
//* Purpose: calculate the apparent longitude of the sun */
//* Arguments: */
//* t : number of Julian centuries since J2000.0 */
//* Return value: */
//* sun's apparent longitude in degrees */
//***********************************************************************/
function calcSunApparentLong(t)
{
var o = calcSunTrueLong(t);
var omega = 125.04 - 1934.136 * t;
var lambda = o - 0.00569 - 0.00478 * Math.sin(degToRad(omega));
return lambda; // in degrees
}
//***********************************************************************/
//* Name: calcMeanObliquityOfEcliptic */
//* Type: Function */
//* Purpose: calculate the mean obliquity of the ecliptic */
//* Arguments: */
//* t : number of Julian centuries since J2000.0 */
//* Return value: */
//* mean obliquity in degrees */
//***********************************************************************/
function calcMeanObliquityOfEcliptic(t)
{
var seconds = 21.448 - t*(46.8150 + t*(0.00059 - t*(0.001813)));
var e0 = 23.0 + (26.0 + (seconds/60.0))/60.0;
return e0; // in degrees
}
//***********************************************************************/
//* Name: calcObliquityCorrection */
//* Type: Function */
//* Purpose: calculate the corrected obliquity of the ecliptic */
//* Arguments: */
//* t : number of Julian centuries since J2000.0 */
//* Return value: */
//* corrected obliquity in degrees */
//***********************************************************************/
function calcObliquityCorrection(t)
{
var e0 = calcMeanObliquityOfEcliptic(t);
var omega = 125.04 - 1934.136 * t;
var e = e0 + 0.00256 * Math.cos(degToRad(omega));
return e; // in degrees
}
//***********************************************************************/
//* Name: calcSunRtAscension */
//* Type: Function */
//* Purpose: calculate the right ascension of the sun */
//* Arguments: */
//* t : number of Julian centuries since J2000.0 */
//* Return value: */
//* sun's right ascension in degrees */
//***********************************************************************/
function calcSunRtAscension(t)
{
var e = calcObliquityCorrection(t);
var lambda = calcSunApparentLong(t);
var tananum = (Math.cos(degToRad(e)) * Math.sin(degToRad(lambda)));
var tanadenom = (Math.cos(degToRad(lambda)));
var alpha = radToDeg(Math.atan2(tananum, tanadenom));
return alpha; // in degrees
}
//***********************************************************************/
//* Name: calcDayOfWeek */
//* Type: Function */
//* Purpose: Derives weekday from Julian Day */
//* Arguments: */
//* juld : Julian Day */
//* Return value: */
//* String containing name of weekday */
//***********************************************************************/
function calcDayOfWeek(juld)
{
var A = (juld + 1.5) % 7;
var DOW = (A==0)?"Sunday":(A==1)?"Monday":(A==2)?"Tuesday":(A==3)?"Wednesday":(A==4)?"Thursday":(A==5)?"Friday":"Saturday";
return DOW;
}
//***********************************************************************/
//* Name: calcDayOfYear */
//* Type: Function */
//* Purpose: Finds numerical day-of-year from mn, day and lp year info */
//* Arguments: */
//* month: January = 1 */
//* day : 1 - 31 */
//* lpyr : 1 if leap year, 0 if not */
//* Return value: */
//* The numerical day of year */
//***********************************************************************/
function calcDayOfYear(mn, dy, lpyr)
{
var k = (lpyr ? 1 : 2);
var doy = Math.floor((275 * mn)/9) - k * Math.floor((mn + 9)/12) + dy -30;
return doy;
}
function isLeapYear(yr)
{
return ((yr % 4 == 0 && yr % 100 != 0) || yr % 400 == 0);
}
// Convert degree angle to radians
function degToRad(angleDeg)
{
return (Math.PI * angleDeg / 180.0);
}
// Convert radian angle to degrees
function radToDeg(angleRad)
{
return (180.0 * angleRad / Math.PI);
}
//***********************************************************************/
//* Name: calcSunDeclination */
//* Type: Function */
//* Purpose: calculate the declination of the sun */
//* Arguments: */
//* t : number of Julian centuries since J2000.0 */
//* Return value: */
//* sun's declination in degrees */
//***********************************************************************/
function calcSunDeclination(t)
{
var e = calcObliquityCorrection(t);
var lambda = calcSunApparentLong(t);
var sint = Math.sin(degToRad(e)) * Math.sin(degToRad(lambda));
var theta = radToDeg(Math.asin(sint));
return theta; // in degrees
}
function calcEquationOfTime(t)
{
var epsilon = calcObliquityCorrection(t);
var l0 = calcGeomMeanLongSun(t);
var e = calcEccentricityEarthOrbit(t);
var m = calcGeomMeanAnomalySun(t);
var y = Math.tan(degToRad(epsilon)/2.0);
y *= y;
var sin2l0 = Math.sin(2.0 * degToRad(l0));
var sinm = Math.sin(degToRad(m));
var cos2l0 = Math.cos(2.0 * degToRad(l0));
var sin4l0 = Math.sin(4.0 * degToRad(l0));
var sin2m = Math.sin(2.0 * degToRad(m));
var Etime = y * sin2l0 - 2.0 * e * sinm + 4.0 * e * y * sinm * cos2l0
- 0.5 * y * y * sin4l0 - 1.25 * e * e * sin2m;
return radToDeg(Etime)*4.0; // in minutes of time
}
function calcHourAngle(time, longitude, eqtime)
{
return (15.0*(time - (longitude/15.0) - (eqtime/60.0)));
// in degrees
}
//function calcSun(riseSetForm, latLongForm, index, index2)
function CalcSunPos(latitude, longitude, hh, mm, ss, year, month, day)
{
// we need a single float value for long and lat
// so if we have deg, minutes and seconds do this: decLat = degs + (mins / 60) + (secs / 3600);
// timenow is GMT time for calculation, in hours since 0Z as float
timenow = hh + mm/60 + ss/3600;
//alert("timenow = " + timenow);
var JD = (calcJD(year, month, day));
var dow = calcDayOfWeek(JD);
var doy = calcDayOfYear(month, day, isLeapYear(year));
var T = calcTimeJulianCent(JD + timenow/24.0);
var R = calcSunRadVector(T);
var alpha = calcSunRtAscension(T);
var theta = calcSunDeclination(T);
var Etime = calcEquationOfTime(T);
var eqTime = Etime;
var solarDec = theta; // in degrees
var earthRadVec = R;
// var solarTimeFix = eqTime - 4.0 * longitude;
var solarTimeFix = eqTime + 4.0 * longitude;
var trueSolarTime = hh * 60.0 + mm + ss/60.0 + solarTimeFix;
// in minutes
while (trueSolarTime > 1440)
{
trueSolarTime -= 1440;
}
//var hourAngle = calcHourAngle(timenow, longitude, eqTime);
var hourAngle = trueSolarTime / 4.0 - 180.0;
// Thanks to Louis Schwarzmayr for finding our error,
// and providing the following 4 lines to fix it:
if (hourAngle < -180) {
hourAngle += 360.0;
}
// alert ("Hour Angle = " + hourAngle);
var haRad = degToRad(hourAngle);
var csz = Math.sin(degToRad(latitude)) * Math.sin(degToRad(solarDec)) + Math.cos(degToRad(latitude)) * Math.cos(degToRad(solarDec)) * Math.cos(haRad);
if (csz > 1.0) {
csz = 1.0;
} else if (csz < -1.0) {
csz = -1.0;
}
var zenith = radToDeg(Math.acos(csz));
var azDenom = ( Math.cos(degToRad(latitude)) * Math.sin(degToRad(zenith)) );
if (Math.abs(azDenom) > 0.001) {
azRad = (( Math.sin(degToRad(latitude)) * Math.cos(degToRad(zenith)) ) - Math.sin(degToRad(solarDec))) / azDenom;
if (Math.abs(azRad) > 1.0) {
if (azRad < 0) {
azRad = -1.0;
} else {
azRad = 1.0;
}
}
var azimuth = 180.0 - radToDeg(Math.acos(azRad));
if (hourAngle > 0.0) {
azimuth = -azimuth;
}
} else {
if (latitude > 0.0) {
azimuth = 180.0;
} else {
azimuth = 0.0;
}
}
if (azimuth < 0.0) {
azimuth += 360.0;
}
exoatmElevation = 90.0 - zenith;
if (exoatmElevation > 85.0) {
refractionCorrection = 0.0;
} else {
te = Math.tan (degToRad(exoatmElevation));
if (exoatmElevation > 5.0) {
refractionCorrection = 58.1 / te - 0.07 / (te*te*te) + 0.000086 / (te*te*te*te*te);
} else if (exoatmElevation > -0.575) {
refractionCorrection = 1735.0 + exoatmElevation * (-518.2 + exoatmElevation * (103.4 + exoatmElevation * (-12.79 + exoatmElevation * 0.711) ) );
} else {
refractionCorrection = -20.774 / te;
}
refractionCorrection = refractionCorrection / 3600.0;
}
solarZen = zenith - refractionCorrection;
var elevation = 90.0 - solarZen;
// results
// alert("azimuth=" + azimuth);
// alert("elevation=" + elevation);
return {azimuth:azimuth,elevation:elevation};
}
//CalcSunPos(latitude, longitude, hh, mm, ss, year, month, day)
//CalcSunPos(48, 16, 10, 0, 0, 2011, 5, 24);
eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('9 17={3i:\'0.1.3\',16:1e-6};l v(){}v.23={e:l(i){8(i<1||i>7.4.q)?w:7.4[i-1]},2R:l(){8 7.4.q},1u:l(){8 F.1x(7.2u(7))},24:l(a){9 n=7.4.q;9 V=a.4||a;o(n!=V.q){8 1L}J{o(F.13(7.4[n-1]-V[n-1])>17.16){8 1L}}H(--n);8 2x},1q:l(){8 v.u(7.4)},1b:l(a){9 b=[];7.28(l(x,i){b.19(a(x,i))});8 v.u(b)},28:l(a){9 n=7.4.q,k=n,i;J{i=k-n;a(7.4[i],i+1)}H(--n)},2q:l(){9 r=7.1u();o(r===0){8 7.1q()}8 7.1b(l(x){8 x/r})},1C:l(a){9 V=a.4||a;9 n=7.4.q,k=n,i;o(n!=V.q){8 w}9 b=0,1D=0,1F=0;7.28(l(x,i){b+=x*V[i-1];1D+=x*x;1F+=V[i-1]*V[i-1]});1D=F.1x(1D);1F=F.1x(1F);o(1D*1F===0){8 w}9 c=b/(1D*1F);o(c<-1){c=-1}o(c>1){c=1}8 F.37(c)},1m:l(a){9 b=7.1C(a);8(b===w)?w:(b<=17.16)},34:l(a){9 b=7.1C(a);8(b===w)?w:(F.13(b-F.1A)<=17.16)},2k:l(a){9 b=7.2u(a);8(b===w)?w:(F.13(b)<=17.16)},2j:l(a){9 V=a.4||a;o(7.4.q!=V.q){8 w}8 7.1b(l(x,i){8 x+V[i-1]})},2C:l(a){9 V=a.4||a;o(7.4.q!=V.q){8 w}8 7.1b(l(x,i){8 x-V[i-1]})},22:l(k){8 7.1b(l(x){8 x*k})},x:l(k){8 7.22(k)},2u:l(a){9 V=a.4||a;9 i,2g=0,n=7.4.q;o(n!=V.q){8 w}J{2g+=7.4[n-1]*V[n-1]}H(--n);8 2g},2f:l(a){9 B=a.4||a;o(7.4.q!=3||B.q!=3){8 w}9 A=7.4;8 v.u([(A[1]*B[2])-(A[2]*B[1]),(A[2]*B[0])-(A[0]*B[2]),(A[0]*B[1])-(A[1]*B[0])])},2A:l(){9 m=0,n=7.4.q,k=n,i;J{i=k-n;o(F.13(7.4[i])>F.13(m)){m=7.4[i]}}H(--n);8 m},2Z:l(x){9 a=w,n=7.4.q,k=n,i;J{i=k-n;o(a===w&&7.4[i]==x){a=i+1}}H(--n);8 a},3g:l(){8 S.2X(7.4)},2d:l(){8 7.1b(l(x){8 F.2d(x)})},2V:l(x){8 7.1b(l(y){8(F.13(y-x)<=17.16)?x:y})},1o:l(a){o(a.K){8 a.1o(7)}9 V=a.4||a;o(V.q!=7.4.q){8 w}9 b=0,2b;7.28(l(x,i){2b=x-V[i-1];b+=2b*2b});8 F.1x(b)},3a:l(a){8 a.1h(7)},2T:l(a){8 a.1h(7)},1V:l(t,a){9 V,R,x,y,z;2S(7.4.q){27 2:V=a.4||a;o(V.q!=2){8 w}R=S.1R(t).4;x=7.4[0]-V[0];y=7.4[1]-V[1];8 v.u([V[0]+R[0][0]*x+R[0][1]*y,V[1]+R[1][0]*x+R[1][1]*y]);1I;27 3:o(!a.U){8 w}9 C=a.1r(7).4;R=S.1R(t,a.U).4;x=7.4[0]-C[0];y=7.4[1]-C[1];z=7.4[2]-C[2];8 v.u([C[0]+R[0][0]*x+R[0][1]*y+R[0][2]*z,C[1]+R[1][0]*x+R[1][1]*y+R[1][2]*z,C[2]+R[2][0]*x+R[2][1]*y+R[2][2]*z]);1I;2P:8 w}},1t:l(a){o(a.K){9 P=7.4.2O();9 C=a.1r(P).4;8 v.u([C[0]+(C[0]-P[0]),C[1]+(C[1]-P[1]),C[2]+(C[2]-(P[2]||0))])}1d{9 Q=a.4||a;o(7.4.q!=Q.q){8 w}8 7.1b(l(x,i){8 Q[i-1]+(Q[i-1]-x)})}},1N:l(){9 V=7.1q();2S(V.4.q){27 3:1I;27 2:V.4.19(0);1I;2P:8 w}8 V},2n:l(){8\'[\'+7.4.2K(\', \')+\']\'},26:l(a){7.4=(a.4||a).2O();8 7}};v.u=l(a){9 V=25 v();8 V.26(a)};v.i=v.u([1,0,0]);v.j=v.u([0,1,0]);v.k=v.u([0,0,1]);v.2J=l(n){9 a=[];J{a.19(F.2F())}H(--n);8 v.u(a)};v.1j=l(n){9 a=[];J{a.19(0)}H(--n);8 v.u(a)};l S(){}S.23={e:l(i,j){o(i<1||i>7.4.q||j<1||j>7.4[0].q){8 w}8 7.4[i-1][j-1]},33:l(i){o(i>7.4.q){8 w}8 v.u(7.4[i-1])},2E:l(j){o(j>7.4[0].q){8 w}9 a=[],n=7.4.q,k=n,i;J{i=k-n;a.19(7.4[i][j-1])}H(--n);8 v.u(a)},2R:l(){8{2D:7.4.q,1p:7.4[0].q}},2D:l(){8 7.4.q},1p:l(){8 7.4[0].q},24:l(a){9 M=a.4||a;o(1g(M[0][0])==\'1f\'){M=S.u(M).4}o(7.4.q!=M.q||7.4[0].q!=M[0].q){8 1L}9 b=7.4.q,15=b,i,G,10=7.4[0].q,j;J{i=15-b;G=10;J{j=10-G;o(F.13(7.4[i][j]-M[i][j])>17.16){8 1L}}H(--G)}H(--b);8 2x},1q:l(){8 S.u(7.4)},1b:l(a){9 b=[],12=7.4.q,15=12,i,G,10=7.4[0].q,j;J{i=15-12;G=10;b[i]=[];J{j=10-G;b[i][j]=a(7.4[i][j],i+1,j+1)}H(--G)}H(--12);8 S.u(b)},2i:l(a){9 M=a.4||a;o(1g(M[0][0])==\'1f\'){M=S.u(M).4}8(7.4.q==M.q&&7.4[0].q==M[0].q)},2j:l(a){9 M=a.4||a;o(1g(M[0][0])==\'1f\'){M=S.u(M).4}o(!7.2i(M)){8 w}8 7.1b(l(x,i,j){8 x+M[i-1][j-1]})},2C:l(a){9 M=a.4||a;o(1g(M[0][0])==\'1f\'){M=S.u(M).4}o(!7.2i(M)){8 w}8 7.1b(l(x,i,j){8 x-M[i-1][j-1]})},2B:l(a){9 M=a.4||a;o(1g(M[0][0])==\'1f\'){M=S.u(M).4}8(7.4[0].q==M.q)},22:l(a){o(!a.4){8 7.1b(l(x){8 x*a})}9 b=a.1u?2x:1L;9 M=a.4||a;o(1g(M[0][0])==\'1f\'){M=S.u(M).4}o(!7.2B(M)){8 w}9 d=7.4.q,15=d,i,G,10=M[0].q,j;9 e=7.4[0].q,4=[],21,20,c;J{i=15-d;4[i]=[];G=10;J{j=10-G;21=0;20=e;J{c=e-20;21+=7.4[i][c]*M[c][j]}H(--20);4[i][j]=21}H(--G)}H(--d);9 M=S.u(4);8 b?M.2E(1):M},x:l(a){8 7.22(a)},32:l(a,b,c,d){9 e=[],12=c,i,G,j;9 f=7.4.q,1p=7.4[0].q;J{i=c-12;e[i]=[];G=d;J{j=d-G;e[i][j]=7.4[(a+i-1)%f][(b+j-1)%1p]}H(--G)}H(--12);8 S.u(e)},31:l(){9 a=7.4.q,1p=7.4[0].q;9 b=[],12=1p,i,G,j;J{i=1p-12;b[i]=[];G=a;J{j=a-G;b[i][j]=7.4[j][i]}H(--G)}H(--12);8 S.u(b)},1y:l(){8(7.4.q==7.4[0].q)},2A:l(){9 m=0,12=7.4.q,15=12,i,G,10=7.4[0].q,j;J{i=15-12;G=10;J{j=10-G;o(F.13(7.4[i][j])>F.13(m)){m=7.4[i][j]}}H(--G)}H(--12);8 m},2Z:l(x){9 a=w,12=7.4.q,15=12,i,G,10=7.4[0].q,j;J{i=15-12;G=10;J{j=10-G;o(7.4[i][j]==x){8{i:i+1,j:j+1}}}H(--G)}H(--12);8 w},30:l(){o(!7.1y){8 w}9 a=[],n=7.4.q,k=n,i;J{i=k-n;a.19(7.4[i][i])}H(--n);8 v.u(a)},1K:l(){9 M=7.1q(),1c;9 n=7.4.q,k=n,i,1s,1n=7.4[0].q,p;J{i=k-n;o(M.4[i][i]==0){2e(j=i+1;j<k;j++){o(M.4[j][i]!=0){1c=[];1s=1n;J{p=1n-1s;1c.19(M.4[i][p]+M.4[j][p])}H(--1s);M.4[i]=1c;1I}}}o(M.4[i][i]!=0){2e(j=i+1;j<k;j++){9 a=M.4[j][i]/M.4[i][i];1c=[];1s=1n;J{p=1n-1s;1c.19(p<=i?0:M.4[j][p]-M.4[i][p]*a)}H(--1s);M.4[j]=1c}}}H(--n);8 M},3h:l(){8 7.1K()},2z:l(){o(!7.1y()){8 w}9 M=7.1K();9 a=M.4[0][0],n=M.4.q-1,k=n,i;J{i=k-n+1;a=a*M.4[i][i]}H(--n);8 a},3f:l(){8 7.2z()},2y:l(){8(7.1y()&&7.2z()===0)},2Y:l(){o(!7.1y()){8 w}9 a=7.4[0][0],n=7.4.q-1,k=n,i;J{i=k-n+1;a+=7.4[i][i]}H(--n);8 a},3e:l(){8 7.2Y()},1Y:l(){9 M=7.1K(),1Y=0;9 a=7.4.q,15=a,i,G,10=7.4[0].q,j;J{i=15-a;G=10;J{j=10-G;o(F.13(M.4[i][j])>17.16){1Y++;1I}}H(--G)}H(--a);8 1Y},3d:l(){8 7.1Y()},2W:l(a){9 M=a.4||a;o(1g(M[0][0])==\'1f\'){M=S.u(M).4}9 T=7.1q(),1p=T.4[0].q;9 b=T.4.q,15=b,i,G,10=M[0].q,j;o(b!=M.q){8 w}J{i=15-b;G=10;J{j=10-G;T.4[i][1p+j]=M[i][j]}H(--G)}H(--b);8 T},2w:l(){o(!7.1y()||7.2y()){8 w}9 a=7.4.q,15=a,i,j;9 M=7.2W(S.I(a)).1K();9 b,1n=M.4[0].q,p,1c,2v;9 c=[],2c;J{i=a-1;1c=[];b=1n;c[i]=[];2v=M.4[i][i];J{p=1n-b;2c=M.4[i][p]/2v;1c.19(2c);o(p>=15){c[i].19(2c)}}H(--b);M.4[i]=1c;2e(j=0;j<i;j++){1c=[];b=1n;J{p=1n-b;1c.19(M.4[j][p]-M.4[i][p]*M.4[j][i])}H(--b);M.4[j]=1c}}H(--a);8 S.u(c)},3c:l(){8 7.2w()},2d:l(){8 7.1b(l(x){8 F.2d(x)})},2V:l(x){8 7.1b(l(p){8(F.13(p-x)<=17.16)?x:p})},2n:l(){9 a=[];9 n=7.4.q,k=n,i;J{i=k-n;a.19(v.u(7.4[i]).2n())}H(--n);8 a.2K(\'\\n\')},26:l(a){9 i,4=a.4||a;o(1g(4[0][0])!=\'1f\'){9 b=4.q,15=b,G,10,j;7.4=[];J{i=15-b;G=4[i].q;10=G;7.4[i]=[];J{j=10-G;7.4[i][j]=4[i][j]}H(--G)}H(--b);8 7}9 n=4.q,k=n;7.4=[];J{i=k-n;7.4.19([4[i]])}H(--n);8 7}};S.u=l(a){9 M=25 S();8 M.26(a)};S.I=l(n){9 a=[],k=n,i,G,j;J{i=k-n;a[i]=[];G=k;J{j=k-G;a[i][j]=(i==j)?1:0}H(--G)}H(--n);8 S.u(a)};S.2X=l(a){9 n=a.q,k=n,i;9 M=S.I(n);J{i=k-n;M.4[i][i]=a[i]}H(--n);8 M};S.1R=l(b,a){o(!a){8 S.u([[F.1H(b),-F.1G(b)],[F.1G(b),F.1H(b)]])}9 d=a.1q();o(d.4.q!=3){8 w}9 e=d.1u();9 x=d.4[0]/e,y=d.4[1]/e,z=d.4[2]/e;9 s=F.1G(b),c=F.1H(b),t=1-c;8 S.u([[t*x*x+c,t*x*y-s*z,t*x*z+s*y],[t*x*y+s*z,t*y*y+c,t*y*z-s*x],[t*x*z-s*y,t*y*z+s*x,t*z*z+c]])};S.3b=l(t){9 c=F.1H(t),s=F.1G(t);8 S.u([[1,0,0],[0,c,-s],[0,s,c]])};S.39=l(t){9 c=F.1H(t),s=F.1G(t);8 S.u([[c,0,s],[0,1,0],[-s,0,c]])};S.38=l(t){9 c=F.1H(t),s=F.1G(t);8 S.u([[c,-s,0],[s,c,0],[0,0,1]])};S.2J=l(n,m){8 S.1j(n,m).1b(l(){8 F.2F()})};S.1j=l(n,m){9 a=[],12=n,i,G,j;J{i=n-12;a[i]=[];G=m;J{j=m-G;a[i][j]=0}H(--G)}H(--12);8 S.u(a)};l 14(){}14.23={24:l(a){8(7.1m(a)&&7.1h(a.K))},1q:l(){8 14.u(7.K,7.U)},2U:l(a){9 V=a.4||a;8 14.u([7.K.4[0]+V[0],7.K.4[1]+V[1],7.K.4[2]+(V[2]||0)],7.U)},1m:l(a){o(a.W){8 a.1m(7)}9 b=7.U.1C(a.U);8(F.13(b)<=17.16||F.13(b-F.1A)<=17.16)},1o:l(a){o(a.W){8 a.1o(7)}o(a.U){o(7.1m(a)){8 7.1o(a.K)}9 N=7.U.2f(a.U).2q().4;9 A=7.K.4,B=a.K.4;8 F.13((A[0]-B[0])*N[0]+(A[1]-B[1])*N[1]+(A[2]-B[2])*N[2])}1d{9 P=a.4||a;9 A=7.K.4,D=7.U.4;9 b=P[0]-A[0],2a=P[1]-A[1],29=(P[2]||0)-A[2];9 c=F.1x(b*b+2a*2a+29*29);o(c===0)8 0;9 d=(b*D[0]+2a*D[1]+29*D[2])/c;9 e=1-d*d;8 F.13(c*F.1x(e<0?0:e))}},1h:l(a){9 b=7.1o(a);8(b!==w&&b<=17.16)},2T:l(a){8 a.1h(7)},1v:l(a){o(a.W){8 a.1v(7)}8(!7.1m(a)&&7.1o(a)<=17.16)},1U:l(a){o(a.W){8 a.1U(7)}o(!7.1v(a)){8 w}9 P=7.K.4,X=7.U.4,Q=a.K.4,Y=a.U.4;9 b=X[0],1z=X[1],1B=X[2],1T=Y[0],1S=Y[1],1M=Y[2];9 c=P[0]-Q[0],2s=P[1]-Q[1],2r=P[2]-Q[2];9 d=-b*c-1z*2s-1B*2r;9 e=1T*c+1S*2s+1M*2r;9 f=b*b+1z*1z+1B*1B;9 g=1T*1T+1S*1S+1M*1M;9 h=b*1T+1z*1S+1B*1M;9 k=(d*g/f+h*e)/(g-h*h);8 v.u([P[0]+k*b,P[1]+k*1z,P[2]+k*1B])},1r:l(a){o(a.U){o(7.1v(a)){8 7.1U(a)}o(7.1m(a)){8 w}9 D=7.U.4,E=a.U.4;9 b=D[0],1l=D[1],1k=D[2],1P=E[0],1O=E[1],1Q=E[2];9 x=(1k*1P-b*1Q),y=(b*1O-1l*1P),z=(1l*1Q-1k*1O);9 N=v.u([x*1Q-y*1O,y*1P-z*1Q,z*1O-x*1P]);9 P=11.u(a.K,N);8 P.1U(7)}1d{9 P=a.4||a;o(7.1h(P)){8 v.u(P)}9 A=7.K.4,D=7.U.4;9 b=D[0],1l=D[1],1k=D[2],1w=A[0],18=A[1],1a=A[2];9 x=b*(P[1]-18)-1l*(P[0]-1w),y=1l*((P[2]||0)-1a)-1k*(P[1]-18),z=1k*(P[0]-1w)-b*((P[2]||0)-1a);9 V=v.u([1l*x-1k*z,1k*y-b*x,b*z-1l*y]);9 k=7.1o(P)/V.1u();8 v.u([P[0]+V.4[0]*k,P[1]+V.4[1]*k,(P[2]||0)+V.4[2]*k])}},1V:l(t,a){o(1g(a.U)==\'1f\'){a=14.u(a.1N(),v.k)}9 R=S.1R(t,a.U).4;9 C=a.1r(7.K).4;9 A=7.K.4,D=7.U.4;9 b=C[0],1E=C[1],1J=C[2],1w=A[0],18=A[1],1a=A[2];9 x=1w-b,y=18-1E,z=1a-1J;8 14.u([b+R[0][0]*x+R[0][1]*y+R[0][2]*z,1E+R[1][0]*x+R[1][1]*y+R[1][2]*z,1J+R[2][0]*x+R[2][1]*y+R[2][2]*z],[R[0][0]*D[0]+R[0][1]*D[1]+R[0][2]*D[2],R[1][0]*D[0]+R[1][1]*D[1]+R[1][2]*D[2],R[2][0]*D[0]+R[2][1]*D[1]+R[2][2]*D[2]])},1t:l(a){o(a.W){9 A=7.K.4,D=7.U.4;9 b=A[0],18=A[1],1a=A[2],2N=D[0],1l=D[1],1k=D[2];9 c=7.K.1t(a).4;9 d=b+2N,2h=18+1l,2o=1a+1k;9 Q=a.1r([d,2h,2o]).4;9 e=[Q[0]+(Q[0]-d)-c[0],Q[1]+(Q[1]-2h)-c[1],Q[2]+(Q[2]-2o)-c[2]];8 14.u(c,e)}1d o(a.U){8 7.1V(F.1A,a)}1d{9 P=a.4||a;8 14.u(7.K.1t([P[0],P[1],(P[2]||0)]),7.U)}},1Z:l(a,b){a=v.u(a);b=v.u(b);o(a.4.q==2){a.4.19(0)}o(b.4.q==2){b.4.19(0)}o(a.4.q>3||b.4.q>3){8 w}9 c=b.1u();o(c===0){8 w}7.K=a;7.U=v.u([b.4[0]/c,b.4[1]/c,b.4[2]/c]);8 7}};14.u=l(a,b){9 L=25 14();8 L.1Z(a,b)};14.X=14.u(v.1j(3),v.i);14.Y=14.u(v.1j(3),v.j);14.Z=14.u(v.1j(3),v.k);l 11(){}11.23={24:l(a){8(7.1h(a.K)&&7.1m(a))},1q:l(){8 11.u(7.K,7.W)},2U:l(a){9 V=a.4||a;8 11.u([7.K.4[0]+V[0],7.K.4[1]+V[1],7.K.4[2]+(V[2]||0)],7.W)},1m:l(a){9 b;o(a.W){b=7.W.1C(a.W);8(F.13(b)<=17.16||F.13(F.1A-b)<=17.16)}1d o(a.U){8 7.W.2k(a.U)}8 w},2k:l(a){9 b=7.W.1C(a.W);8(F.13(F.1A/2-b)<=17.16)},1o:l(a){o(7.1v(a)||7.1h(a)){8 0}o(a.K){9 A=7.K.4,B=a.K.4,N=7.W.4;8 F.13((A[0]-B[0])*N[0]+(A[1]-B[1])*N[1]+(A[2]-B[2])*N[2])}1d{9 P=a.4||a;9 A=7.K.4,N=7.W.4;8 F.13((A[0]-P[0])*N[0]+(A[1]-P[1])*N[1]+(A[2]-(P[2]||0))*N[2])}},1h:l(a){o(a.W){8 w}o(a.U){8(7.1h(a.K)&&7.1h(a.K.2j(a.U)))}1d{9 P=a.4||a;9 A=7.K.4,N=7.W.4;9 b=F.13(N[0]*(A[0]-P[0])+N[1]*(A[1]-P[1])+N[2]*(A[2]-(P[2]||0)));8(b<=17.16)}},1v:l(a){o(1g(a.U)==\'1f\'&&1g(a.W)==\'1f\'){8 w}8!7.1m(a)},1U:l(a){o(!7.1v(a)){8 w}o(a.U){9 A=a.K.4,D=a.U.4,P=7.K.4,N=7.W.4;9 b=(N[0]*(P[0]-A[0])+N[1]*(P[1]-A[1])+N[2]*(P[2]-A[2]))/(N[0]*D[0]+N[1]*D[1]+N[2]*D[2]);8 v.u([A[0]+D[0]*b,A[1]+D[1]*b,A[2]+D[2]*b])}1d o(a.W){9 c=7.W.2f(a.W).2q();9 N=7.W.4,A=7.K.4,O=a.W.4,B=a.K.4;9 d=S.1j(2,2),i=0;H(d.2y()){i++;d=S.u([[N[i%3],N[(i+1)%3]],[O[i%3],O[(i+1)%3]]])}9 e=d.2w().4;9 x=N[0]*A[0]+N[1]*A[1]+N[2]*A[2];9 y=O[0]*B[0]+O[1]*B[1]+O[2]*B[2];9 f=[e[0][0]*x+e[0][1]*y,e[1][0]*x+e[1][1]*y];9 g=[];2e(9 j=1;j<=3;j++){g.19((i==j)?0:f[(j+(5-i)%3)%3])}8 14.u(g,c)}},1r:l(a){9 P=a.4||a;9 A=7.K.4,N=7.W.4;9 b=(A[0]-P[0])*N[0]+(A[1]-P[1])*N[1]+(A[2]-(P[2]||0))*N[2];8 v.u([P[0]+N[0]*b,P[1]+N[1]*b,(P[2]||0)+N[2]*b])},1V:l(t,a){9 R=S.1R(t,a.U).4;9 C=a.1r(7.K).4;9 A=7.K.4,N=7.W.4;9 b=C[0],1E=C[1],1J=C[2],1w=A[0],18=A[1],1a=A[2];9 x=1w-b,y=18-1E,z=1a-1J;8 11.u([b+R[0][0]*x+R[0][1]*y+R[0][2]*z,1E+R[1][0]*x+R[1][1]*y+R[1][2]*z,1J+R[2][0]*x+R[2][1]*y+R[2][2]*z],[R[0][0]*N[0]+R[0][1]*N[1]+R[0][2]*N[2],R[1][0]*N[0]+R[1][1]*N[1]+R[1][2]*N[2],R[2][0]*N[0]+R[2][1]*N[1]+R[2][2]*N[2]])},1t:l(a){o(a.W){9 A=7.K.4,N=7.W.4;9 b=A[0],18=A[1],1a=A[2],2M=N[0],2L=N[1],2Q=N[2];9 c=7.K.1t(a).4;9 d=b+2M,2p=18+2L,2m=1a+2Q;9 Q=a.1r([d,2p,2m]).4;9 e=[Q[0]+(Q[0]-d)-c[0],Q[1]+(Q[1]-2p)-c[1],Q[2]+(Q[2]-2m)-c[2]];8 11.u(c,e)}1d o(a.U){8 7.1V(F.1A,a)}1d{9 P=a.4||a;8 11.u(7.K.1t([P[0],P[1],(P[2]||0)]),7.W)}},1Z:l(a,b,c){a=v.u(a);a=a.1N();o(a===w){8 w}b=v.u(b);b=b.1N();o(b===w){8 w}o(1g(c)==\'1f\'){c=w}1d{c=v.u(c);c=c.1N();o(c===w){8 w}}9 d=a.4[0],18=a.4[1],1a=a.4[2];9 e=b.4[0],1W=b.4[1],1X=b.4[2];9 f,1i;o(c!==w){9 g=c.4[0],2l=c.4[1],2t=c.4[2];f=v.u([(1W-18)*(2t-1a)-(1X-1a)*(2l-18),(1X-1a)*(g-d)-(e-d)*(2t-1a),(e-d)*(2l-18)-(1W-18)*(g-d)]);1i=f.1u();o(1i===0){8 w}f=v.u([f.4[0]/1i,f.4[1]/1i,f.4[2]/1i])}1d{1i=F.1x(e*e+1W*1W+1X*1X);o(1i===0){8 w}f=v.u([b.4[0]/1i,b.4[1]/1i,b.4[2]/1i])}7.K=a;7.W=f;8 7}};11.u=l(a,b,c){9 P=25 11();8 P.1Z(a,b,c)};11.2I=11.u(v.1j(3),v.k);11.2H=11.u(v.1j(3),v.i);11.2G=11.u(v.1j(3),v.j);11.36=11.2I;11.35=11.2H;11.3j=11.2G;9 $V=v.u;9 $M=S.u;9 $L=14.u;9 $P=11.u;',62,206,'||||elements|||this|return|var||||||||||||function|||if||length||||create|Vector|null|||||||||Math|nj|while||do|anchor||||||||Matrix||direction||normal||||kj|Plane|ni|abs|Line|ki|precision|Sylvester|A2|push|A3|map|els|else||undefined|typeof|contains|mod|Zero|D3|D2|isParallelTo|kp|distanceFrom|cols|dup|pointClosestTo|np|reflectionIn|modulus|intersects|A1|sqrt|isSquare|X2|PI|X3|angleFrom|mod1|C2|mod2|sin|cos|break|C3|toRightTriangular|false|Y3|to3D|E2|E1|E3|Rotation|Y2|Y1|intersectionWith|rotate|v12|v13|rank|setVectors|nc|sum|multiply|prototype|eql|new|setElements|case|each|PA3|PA2|part|new_element|round|for|cross|product|AD2|isSameSizeAs|add|isPerpendicularTo|v22|AN3|inspect|AD3|AN2|toUnitVector|PsubQ3|PsubQ2|v23|dot|divisor|inverse|true|isSingular|determinant|max|canMultiplyFromLeft|subtract|rows|col|random|ZX|YZ|XY|Random|join|N2|N1|D1|slice|default|N3|dimensions|switch|liesIn|translate|snapTo|augment|Diagonal|trace|indexOf|diagonal|transpose|minor|row|isAntiparallelTo|ZY|YX|acos|RotationZ|RotationY|liesOn|RotationX|inv|rk|tr|det|toDiagonalMatrix|toUpperTriangular|version|XZ'.split('|'),0,{}))
\ No newline at end of file
/*
*! -----------------------------------------------------------------------------**
*! FILE NAME : translate.js
*! REVISION : 1.0
*! DESCRIPTION: ajax request for translation
*! Copyright (C) 2011 Elphel, Inc.
*!
*! -----------------------------------------------------------------------------**
*! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*!
*! It means that the program's users have the four essential freedoms:
*!
*! * The freedom to run the program, for any purpose (freedom 0).
*! * The freedom to study how the program works, and change it to make it do what you wish (freedom 1).
*! Access to the source code is a precondition for this.
*! * The freedom to redistribute copies so you can help your neighbor (freedom 2).
*! * The freedom to distribute copies of your modified versions to others (freedom 3).
*!
*! By doing this you can give the whole community a chance to benefit from your changes.
*! Access to the source code is a precondition for this.
*! -----------------------------------------------------------------------------**
*/
function translate_request(language){
$.ajax({
url: "translate.php",
type: "GET",
data: "language="+language,
async: false,
success: function(xml){
var child;
var titles = xml.getElementsByTagName("Titles")[0];
var contents = xml.getElementsByTagName("Contents")[0];
//process titles
child = titles.firstChild;
for (var i=0; i<titles.childNodes.length; i++) {
if (child.nodeName=="title") document.title = child.firstChild.nodeValue;
$("#"+child.nodeName).attr("title",child.firstChild.nodeValue);
child = child.nextSibling;
}
//process contents
child = contents.firstChild;
for (var i=0; i<contents.childNodes.length; i++) {
$("#"+child.nodeName).html(child.firstChild.nodeValue);
child = child.nextSibling;
}
}
});
}
\ No newline at end of file
/*!*******************************************************************************
*! FILE NAME : useful_functions.js
*! DESCRIPTION: some common specific xml parsing
*! Copyright (C) 2011 Elphel, Inc
*! -----------------------------------------------------------------------------**
*! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! The four essential freedoms with GNU GPL software:
*! * the freedom to run the program for any purpose
*! * the freedom to study how the program works and change it to make it do what you wish
*! * the freedom to redistribute copies so you can help your neighbor
*! * the freedom to distribute copies of your modified versions to others
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------**
*!
*/
//List:
//function ObjectToXMLString(obj,tab_str,wrap)
//function XMLString_CreateNode(prefix,tagname,value)
//function XMLString_Wrap(prefix,tagname,str)
//function XMLString_AddXMLHeader(str,root)
//function XMLString_AddKMLHeader(str,root)
//function XMLToObject(xml,obj)
//I. Array (multi-D specially formatted associative array) to XML-formatted string
// function ArrayToXMLString(obj,tab_str,wrap){
// var add_tab = (wrap=="")? "":"\t";
// var disable_wrap = false;
// var tmp_str = "";
// var tmp_tmp_str= "";
// for (key in obj) {
// if (typeof(obj[key])!="object") {
// tmp_str += XMLString_CreateNode(tab_str+add_tab,key,obj[key]);
// }
// else {
// if(parseInt(key)==key) disable_wrap = true;
//
// if(parseInt(key)==key)
// tmp_tmp_str = ArrayToXMLString(obj[key],tab_str,wrap);
// else if ((typeof(obj[key][0])!="object")&&(typeof(obj[key][0])!="undefined")) {
// tmp_tmp_str = XMLString_CreateNode(tab_str+add_tab,key,obj[key][0]);
// }
// else
// tmp_tmp_str = ArrayToXMLString(obj[key],tab_str+add_tab,key);
//
// tmp_str += tmp_tmp_str;
// }
// }
// if (!disable_wrap) tmp_str = XMLString_Wrap(tab_str,wrap,tmp_str);
// return tmp_str;
// }
function ArrayToXMLString(obj,tab_str,wrap){
var tmp_str = "";
for (var i=0;i<obj.length;i++) {
tmp_str += ArrayToXMLString_recursive(obj[i],tab_str,wrap);
}
return tmp_str;
}
function ArrayToXMLString_recursive(obj,tab_str,wrap){
var add_tab = (wrap=="")? "":"\t";
var tmp_str = "";
var tmp_tmp_str= "";
for (key in obj) {
if (typeof(obj[key])!="object") {
tmp_str += XMLString_CreateNode(tab_str+add_tab,key,obj[key]);
}
else {
if ((typeof(obj[key][0])!="object")&&(typeof(obj[key][0])!="undefined")) {
tmp_tmp_str = XMLString_CreateNode(tab_str+add_tab,key,obj[key][0]);
}
else
tmp_tmp_str = ArrayToXMLString_recursive(obj[key],tab_str+add_tab,key);
tmp_str += tmp_tmp_str;
}
}
tmp_str = XMLString_Wrap(tab_str,wrap,tmp_str);
return tmp_str;
}
function XMLString_CreateNode(prefix,tagname,value){
return (prefix+"<"+tagname+">"+value+"</"+tagname+">\n");
}
function XMLString_Wrap(prefix,tagname,str){
if (str=="") return str;
else if (tagname=="") return str;
else return (prefix+"<"+tagname+">\n"+str+prefix+"</"+tagname+">\n");
}
function XMLString_AddXMLHeader(str,root){
return ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<"+root+">\n"+str+"</"+root+">");
}
function XMLString_AddKMLHeader(str,root){
return ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<kml xmlns=\"http://earth.google.com/kml/2.2\">\n<"+root+">\n"+str+"</"+root+">\n</kml>");
}
//II. XML to Array (same as multi-D associative array)
// function XMLToArray(xml){
// var tmp = xml.childNodes;
// var obj = new Array();
// for (var i=0;i<tmp.length;i++) {
// if (tmp[i].nodeType==1) {
// if (tmp[i].firstChild!=null) { // the node is not empty
// if (obj[tmp[i].nodeName]==undefined) obj[tmp[i].nodeName] = new Array();
// var tmp_len = obj[tmp[i].nodeName].length;
// if (obj[tmp[i].nodeName][tmp_len]==undefined) obj[tmp[i].nodeName][tmp_len] = new Array();
// if ((tmp[i].firstChild.nodeValue==false)||(tmp[i].firstChild.nodeValue==null)) { // has subnodes
// // recursive iteration
// obj[tmp[i].nodeName][tmp_len] = XMLToArray(tmp[i]);
// }else{ // assign value
// obj[tmp[i].nodeName][tmp_len] = tmp[i].firstChild.nodeValue;
// }
// }
// //skip empty node, example: <exmpl></exmpl>
// /*else{
// obj[tmp[i].nodeName] = "undefined";
// }*/
// }
// }
// return obj;
// }
function XMLToArray(xml){
var tmp = xml.childNodes;
var obj = new Array();
if (tmp[0].nodeType==1) {
//console.log(tmp[0].nodeName);
tmp = tmp[0].childNodes; // enter top tag
if (tmp[1].nodeType==1) {
//console.log(tmp[1].nodeName);
tmp = tmp[1].childNodes; // enter top sub-tag
for (var i=0;i<tmp.length;i++) {
if (tmp[i].nodeType==1) {
var tmp_arr = XMLToArray_recursive(tmp[i]);
if (Object.keys(tmp_arr).length!=0) obj[obj.length] = tmp_arr;
}
}
}
}
return obj;
}
function XMLToArray_recursive(xml){
var tmp = xml.childNodes;
var obj = new Array();
for (var i=0;i<tmp.length;i++) {
if (tmp[i].nodeType==1) {
if (tmp[i].firstChild!=null) { // the node is not empty
if (obj[tmp[i].nodeName]==undefined) obj[tmp[i].nodeName] = new Array();
if ((tmp[i].firstChild.nodeValue==false)||(tmp[i].firstChild.nodeValue==null)) { // has subnodes
// recursive iteration
obj[tmp[i].nodeName] = XMLToArray_recursive(tmp[i]);
}else{ // assign value
obj[tmp[i].nodeName] = tmp[i].firstChild.nodeValue;
}
}
//skip empty node, example: <exmpl></exmpl>
/*else{
obj[tmp[i].nodeName] = "undefined";
}*/
}
}
return obj;
}
/*
*! -----------------------------------------------------------------------------**
*! FILE NAME : webg_subs.js
*! REVISION : 1.0
*! DESCRIPTION: webgl sub procedures
*! Copyright (C) 2011 Elphel, Inc.
*!
*! -----------------------------------------------------------------------------**
*! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*!
*! It means that the program's users have the four essential freedoms:
*!
*! * The freedom to run the program, for any purpose (freedom 0).
*! * The freedom to study how the program works, and change it to make it do what you wish (freedom 1).
*! Access to the source code is a precondition for this.
*! * The freedom to redistribute copies so you can help your neighbor (freedom 2).
*! * The freedom to distribute copies of your modified versions to others (freedom 3).
*!
*! By doing this you can give the whole community a chance to benefit from your changes.
*! Access to the source code is a precondition for this.
*! -----------------------------------------------------------------------------**
*/
function initGL(canvas) {
try {
gl = canvas.getContext("experimental-webgl");
gl.viewportWidth = canvas.width;
gl.viewportHeight = canvas.height;
} catch(e) {
}
if (!gl) {
//alert("Could not initialise WebGL. List of supported browsers: http://www.khronos.org/webgl/wiki/Getting_a_WebGL_Implementation");
//window.open("error_no_webgl.html", "Error", 'width=600,height=5,left=5,top=100');
var top = window.innerHeight;
var left = window.innerWidth;
top = (top/2)-$('#error_no_webgl').height()/2;
left = (left/2)-$('#error_no_webgl').width()/2;
$('#error_no_webgl').css({top: top+'px',left: left+'px'});
$('#error_no_webgl').show();
$('#idSettingsDialog').hide();
}
}
function getShader(gl, id) {
var shaderScript = document.getElementById(id);
if (!shaderScript) {
return null;
}
var str = "";
var k = shaderScript.firstChild;
while (k) {
if (k.nodeType == 3) {
str += k.textContent;
}
k = k.nextSibling;
}
var shader;
if (shaderScript.type == "x-shader/x-fragment") {
shader = gl.createShader(gl.FRAGMENT_SHADER);
} else if (shaderScript.type == "x-shader/x-vertex") {
shader = gl.createShader(gl.VERTEX_SHADER);
} else {
return null;
}
gl.shaderSource(shader, str);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert(gl.getShaderInfoLog(shader));
return null;
}
return shader;
}
var shaderProgram;
function initShaders() {
var fragmentShader = getShader(gl, "shader-fs");
var vertexShader = getShader(gl, "shader-vs");
shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert("Could not initialise shaders");
}
gl.useProgram(shaderProgram);
shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord");
gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute);
shaderProgram.vertexNormalAttribute = gl.getAttribLocation(shaderProgram, "aVertexNormal");
gl.enableVertexAttribArray(shaderProgram.vertexNormalAttribute);
shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram,"uMVMatrix");
shaderProgram.nMatrixUniform = gl.getUniformLocation(shaderProgram, "uNMatrix");
shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler");
shaderProgram.alphaUniform = gl.getUniformLocation(shaderProgram, "uAlpha");
shaderProgram.useLightingUniform = gl.getUniformLocation(shaderProgram, "uUseLighting");
shaderProgram.ambientColorUniform = gl.getUniformLocation(shaderProgram, "uAmbientColor");
shaderProgram.lightingDirectionUniform = gl.getUniformLocation(shaderProgram, "uLightingDirection");
shaderProgram.directionalColorUniform = gl.getUniformLocation(shaderProgram, "uDirectionalColor");
}
function handleLoadedTextures(texture,index,subindex) {
//alert (index+":"+subindex);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.image); // actual transfer to the graphic card
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.bindTexture(gl.TEXTURE_2D, null);
panoLoadedSubTextures[index]++;
if (mapIndices[index]==0){
if (panoLoadedSubTextures[index]>=numSubTextures){
switchPanorama(); // was pointing to the next node to go
} else {
showProgress (panoLoadedSubTextures[index]/numSubTextures);
}
}
}
function initTextures() { // do not start actual loading
for (var i=0; i < panoTexturesSrc.length; i++) for (var j=0; j < numSubTextures; j++) {
panoImages[i][j]=new Image();
panoTextures[i][j] = gl.createTexture();
panoTextures[i][j].image = panoImages[i][j];
panoImages[i][j].index=i;
panoImages[i][j].subindex=j;
panoImages[i][j].onload= function() {
handleLoadedTextures(panoTextures[this.index][this.subindex],this.index,this.subindex);
}
}
}
function loadTexture(number) {
loadedSubTextures=0;
for (var j=0; j < numSubTextures; j++) {
if (numSubTextures==1) {
panoImages[number][j].src=panoTexturesSrc[number];
} else {
var dotIndex=panoTexturesSrc[number].lastIndexOf('.');
var basename= panoTexturesSrc[number].substring(0,dotIndex);
var ext= panoTexturesSrc[number].substring(dotIndex+1,panoTexturesSrc[number].length);
//alert ("loadTexture("+number+"), source="+basename+"_"+(j+1)+"_"+numSubTextures+"."+ext);
panoImages[number][j].src=basename+"_"+(j+1)+"_"+numSubTextures+"."+ext;
}
panoLoadedSubTextures[number]=0;
if (mapIndices[number]==0) showProgress (0);
}
}
function handleLoadedArrowTexture(texture) {
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.image);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.bindTexture(gl.TEXTURE_2D, null);
}
var arrowTexture;
function initArrowTexture() {
arrowTexture = gl.createTexture();
arrowTexture.image = new Image();
arrowTexture.image.onload = function() {
handleLoadedArrowTexture(arrowTexture)
}
arrowTexture.image.src = "files/arrow.png";
}
var eyesisTextureSrc =[ "files/eyesis.jpeg","files/eyesis_grey.jpeg","files/eyesis_selected.jpeg","files/eyesis.jpeg"];
var eyesisTexture = Array(eyesisTextureSrc.length);
function initEyesisTexture() {
for (var i=0;i<eyesisTextureSrc.length;i++) {
eyesisTexture[i] = gl.createTexture();
eyesisTexture[i].image = new Image();
eyesisTexture[i].image.index = i;
eyesisTexture[i].image.onload = function() {
handleLoadedArrowTexture(eyesisTexture[this.index])
}
eyesisTexture[i].image.src = eyesisTextureSrc[i];
}
}
var sunTextureSrc ="files/sun.jpeg";
var sunTexture;
function initSunTexture() {
sunTexture = gl.createTexture();
sunTexture.image = new Image();
sunTexture.image.onload = function() {
handleLoadedArrowTexture(sunTexture)
}
sunTexture.image.src = sunTextureSrc;
}
var footprintsBackpackTextureSrc = ["files/footprints.png","files/footprints_grey.png","files/footprints_selected.png","files/footprints.png"];
var footprintsBackpackTexture= Array(footprintsBackpackTextureSrc.length);;
function initFootprintsBackpackTexture() {
for (var i=0;i<footprintsBackpackTextureSrc.length;i++) {
footprintsBackpackTexture[i] = gl.createTexture();
footprintsBackpackTexture[i].image = new Image();
footprintsBackpackTexture[i].image.index = i;
footprintsBackpackTexture[i].image.onload = function() {
handleLoadedArrowTexture(footprintsBackpackTexture[this.index])
}
footprintsBackpackTexture[i].image.src = footprintsBackpackTextureSrc[i];
}
}
var panoVertexPositionBuffer;
var panoVertexNormalBuffer;
var panoVertexTextureCoordBuffer;
var panoVertexIndexBuffer;
var subDivLong;
var subDivLat;
function initBuffers() {
initBuffersPano();
initArrowBuffers();
initBuffersSun();
initBuffersEyesis();
initBuffersFootprintsBackpack(0.2);
initDotBuffers();
}
function initBuffersPano() {
panoVertexPositionBuffer= Array(numSubTextures);
panoVertexNormalBuffer= Array(numSubTextures);
panoVertexTextureCoordBuffer= Array(numSubTextures);
panoVertexIndexBuffer= Array(numSubTextures);
subDivLong=1;
subDivLat=1;
var latitudeBands = 128;//32
var longitudeBands = 128;
// var subDivLong=1;
// var subDivLat=1;
for (var s=numSubTextures; s>1; s/=2) {
if (subDivLong> subDivLat) subDivLat*= 2;
else subDivLong*=2;
}
var longitudeSubBands=longitudeBands/subDivLong;
var latitudeSubBands= latitudeBands/subDivLat;
// currently, just for testing the panorama will be split in vertical bands (2?),
for (var segmentLat=0;segmentLat<subDivLat;segmentLat++) for (var segmentLong=0;segmentLong<subDivLong;segmentLong++){
var segment=segmentLat*subDivLong+segmentLong;
var vertexPositionData = [];
var normalData = [];
var textureCoordData = [];
/// alert ("segmentLat="+segmentLat+"\n"+ "segmentLong="+segmentLong+"\n"+ "segment="+segment+"\n");
for (var latNumber = segmentLat* latitudeSubBands; latNumber <= (segmentLat + 1)* latitudeSubBands; latNumber++) {
var theta = latNumber * Math.PI / latitudeBands;
var sinTheta = Math.sin(theta);
var cosTheta = Math.cos(theta);
for (var longNumber = segmentLong* longitudeSubBands; longNumber <= (segmentLong+1)* longitudeSubBands; longNumber++) {
var phi = longNumber * 2 * Math.PI / longitudeBands;
var sinPhi = Math.sin(phi);
var cosPhi = Math.cos(phi);
var x = cosPhi * sinTheta;
var y = cosTheta;
var z = sinPhi * sinTheta;
var u = ((longNumber- (segmentLong* longitudeSubBands) ) / longitudeSubBands); // for the inside view
var v = 1 - ((latNumber - (segmentLat* latitudeSubBands))/ latitudeSubBands);
normalData.push(x);
normalData.push(y);
normalData.push(z);
textureCoordData.push(u);
textureCoordData.push(v);
vertexPositionData.push(worldRadius * x);
vertexPositionData.push(worldRadius * y);
vertexPositionData.push(worldRadius * z);
}
}
var indexData = [];
for (var latNumber = 0; latNumber < latitudeSubBands; latNumber++) {
for (var longNumber = 0; longNumber < longitudeSubBands; longNumber++) {
var first = (latNumber * (longitudeSubBands + 1)) + longNumber;
var second = first + longitudeSubBands + 1;
indexData.push(first);
indexData.push(second);
indexData.push(first + 1);
indexData.push(second);
indexData.push(second + 1);
indexData.push(first + 1);
}
}
panoVertexNormalBuffer[segment] = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, panoVertexNormalBuffer[segment]);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(normalData), gl.STATIC_DRAW);
panoVertexNormalBuffer[segment].itemSize = 3;
panoVertexNormalBuffer[segment].numItems = normalData.length / 3;
panoVertexTextureCoordBuffer[segment] = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, panoVertexTextureCoordBuffer[segment]);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoordData), gl.STATIC_DRAW);
panoVertexTextureCoordBuffer[segment].itemSize = 2;
panoVertexTextureCoordBuffer[segment].numItems = textureCoordData.length / 2;
panoVertexPositionBuffer[segment] = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, panoVertexPositionBuffer[segment]);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexPositionData), gl.STATIC_DRAW);
panoVertexPositionBuffer[segment].itemSize = 3;
panoVertexPositionBuffer[segment].numItems = vertexPositionData.length / 3;
panoVertexIndexBuffer[segment] = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, panoVertexIndexBuffer[segment]);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indexData), gl.STREAM_DRAW);
panoVertexIndexBuffer[segment].itemSize = 1;
panoVertexIndexBuffer[segment].numItems = indexData.length;
}
// alert ("subDivLong="+subDivLong+"\n"+"subDivLat="+subDivLat+"\n"+ "longitudeSubBands="+longitudeSubBands+"\n"+"latitudeSubBands="+latitudeSubBands+"\n");
}
var arrowVertexPositionBuffer;
var arrowVertexIndexBuffer;
var arrowVertexTextureCoordBuffer;
var arrowVertexNormalBuffer;
function initArrowBuffers() {
arrowVertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, arrowVertexPositionBuffer);
var vertices = [
0.0, 0.0, -4.0,
0.5, 0.0, 0.0,
0.25, 0.0, 0.0,
0.25, 0.0, 4.0,
-0.25, 0.0, 4.0,
-0.25, 0.0, 0.0,
-0.5, 0.0, 0.0
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
arrowVertexPositionBuffer.itemSize = 3;
arrowVertexPositionBuffer.numItems = 7;
arrowVertexTextureCoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, arrowVertexTextureCoordBuffer);
var textureCoords = [
0.5, 1.0,
0.75, 0.5,
0.625,0.5,
0.625,0.0,
0.375,0.0,
0.375,0.5,
0.25, 0.5
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoords), gl.STATIC_DRAW);
arrowVertexTextureCoordBuffer.itemSize = 2;
arrowVertexTextureCoordBuffer.numItems = 7;
arrowVertexNormalBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, arrowVertexNormalBuffer);
var vertexNormals = [
0.0, 1.0, 0.0,
0.0, 1.0, 0.0,
0.0, 1.0, 0.0,
0.0, 1.0, 0.0,
0.0, 1.0, 0.0,
0.0, 1.0, 0.0,
0.0, 1.0, 0.0
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexNormals), gl.STATIC_DRAW);
arrowVertexNormalBuffer.itemSize = 3;
arrowVertexNormalBuffer.numItems = 7;
arrowVertexIndexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, arrowVertexIndexBuffer);
var arrowVertexIndices = [
0, 1, 6,
5, 2, 3,
5, 3, 4
]
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(arrowVertexIndices), gl.STATIC_DRAW);
arrowVertexIndexBuffer.itemSize = 1;
arrowVertexIndexBuffer.numItems = 9;
}
var eyesisVertexPositionBuffer;
var eyesisVertexNormalBuffer;
var eyesisVertexTextureCoordBuffer;
var eyesisVertexIndexBuffer;
function initBuffersEyesis() {
var divs=8; // 2 - shade separator (21mm), 6 - hole (60mm) for each camera
var subDivs=4; //8; //2; // subdivide each unit (see above) for smooth cylinder
var symmetry=8; // number of camera modules
var allDivs=subDivs*divs;
var scale =0.001; // mm/m
var cavityIndex=20; // 9; // next 6
var cavityHeight=22; //5; // (not counting points on the edge
var angleFin=0.01; //half angle thickness of a fin, radians
var deltaR1=2; // outer shade walls
var deltaR2=45;// distance to side filters from the outer shade
var topBottomThickness=2;
var cavityLong= subDivs+1; // +/-
var cylinderPoints = [ // axis, radius
70.625,0, // 0
70.625,40, // 1
70.625,40, // 2
40.75, 40, // 3
40.75,40, // 4
40.75, 55, // 5
40.75,55, // 6
79.25, 55, // 7
79.25,55, // 8
79.25, 50, // 9
79.25,50, //10
80.75, 50, //11
80.75,50, //12
80.75,62.6, //13
80.75,62.6, //14
59.5, 62.6, //15
59.5, 62.6, //16
59.5, 105, //17
59.5, 105, //18
46.5, 105, //19
30, 105, // needed for the side lens cavity 18
25, 105, // needed for the side lens cavity 19
20, 105, // needed for the side lens cavity 20
// extra divisions to increase the size of the lens part
16, 105, // needed for the side lens cavity 21
14, 105, // needed for the side lens cavity 22
12, 105, // needed for the side lens cavity 23
10, 105, // needed for the side lens cavity 24
8, 105, // needed for the side lens cavity 25
6, 105, // needed for the side lens cavity 26
4, 105, // needed for the side lens cavity 27
2, 105, // needed for the side lens cavity 28
0, 105, // needed for the side lens cavity 29
-2, 105, // needed for the side lens cavity 30
-4, 105, // needed for the side lens cavity 31
-6, 105, // needed for the side lens cavity 32
-8, 105, // needed for the side lens cavity 33
-10, 105, // needed for the side lens cavity 34
-12, 105, // needed for the side lens cavity 35
-14, 105, // needed for the side lens cavity 36
-16, 105, // needed for the side lens cavity 37
-20, 105, // needed for the side lens cavity 38
-25, 105, // needed for the side lens cavity 39
-30, 105, // needed for the side lens cavity 40
-47.5, 105, // 41
-61.5, 105, // 42
-61.5, 105, // 43
-61.5, 54.1, // 44
-61.5, 54.1, // 45
-168.95, 54.1, // 46
-168.95,54.1, // 47
-171.25, 56.4, // 48
-171.25,56.4, // 49
-184.25, 56.4, // 50
-184.25,56.4, // 51
-185.75, 59.5, // 52
-185.75,59.5, // 53
-191.25, 59.5, // 54
-191.25,59.5, // 55
-251.25, 32.5, // 56
-251.25,32.5, // 57
-251.25, 30.1625,//58
-251.25,30.1625,//59
-1000, 30.1625 //60
];
var latitudeBands = cylinderPoints.length/2-1;
var longitudeBands = allDivs*symmetry;
var vertexPositionData = [];
var textureCoordData = [];
for (var latNumber = 0; latNumber <= latitudeBands; latNumber++) {
var h0=cylinderPoints[2*latNumber]*scale;
var r0=cylinderPoints[2*latNumber+1]*scale;
var symLong;
for (var longNumber = 0; longNumber <= longitudeBands; longNumber++) {
var r=r0;
var h=h0;
var phi = longNumber * 2 * Math.PI / longitudeBands;
symLong= longNumber-allDivs*Math.floor(longNumber/allDivs);
if (symLong>(allDivs/2)) symLong=allDivs-symLong;
var v = 1 - (latNumber / latitudeBands);
var u = 1 - 2*(symLong / allDivs);
if ((latNumber>=cavityIndex) && (latNumber<= (cavityIndex+cavityHeight)) && (symLong>=cavityLong)) {
var longNum0=allDivs*Math.floor(longNumber/allDivs); // number of longitude steps till the beginning of this module
var longNum1=longNumber-longNum0; // number of longitude steps since the beginning of this module
var phi0 = longNum0 * 2 * Math.PI / longitudeBands; // angle at the beginning of this module
var phi0a=phi0+ (cavityLong-1)*2 * Math.PI / longitudeBands; // angle at the outer edge of this module
var phi0b=phi0+angleFin;
var phi1 = (longNum0 + allDivs )* 2 * Math.PI / longitudeBands; // angle at the beginning of this module
var phi1a=phi1-(cavityLong-1)*2 * Math.PI / longitudeBands; // angle at the outer edge of this module
var phi1b=phi1-angleFin;
if (longNum1<=(cavityLong+1)) phi=phi0a;
else if (longNum1>=(allDivs-cavityLong-1)) phi=phi1a;
else if (longNum1==(cavityLong+2)) phi=phi0b;
else if (longNum1==(allDivs-cavityLong-2)) phi=phi1b;
else phi=phi0b+(phi1b-phi0b)*(longNum1-cavityLong-3)/(allDivs-2*cavityLong-6);
if ((symLong==cavityLong) || (latNumber== cavityIndex) || (latNumber==(cavityIndex+cavityHeight))) r=r0;
else if ((symLong==(cavityLong+1)) || (symLong==(cavityLong+2) ||
(latNumber== (cavityIndex+1)) ||
(latNumber==(cavityIndex+2)) ||
(latNumber==(cavityIndex+cavityHeight-2)) ||
(latNumber==(cavityIndex+cavityHeight-1)))) r=r0-deltaR1*scale;
else r=r0-deltaR2*scale;
if (latNumber<= (cavityIndex+1)) h=cylinderPoints[2*(cavityIndex-1)]*scale;
else if (latNumber>= (cavityIndex+cavityHeight-1)) h=cylinderPoints[2*(cavityIndex+cavityHeight+1)]*scale;
else if (latNumber== (cavityIndex+2)) h=(cylinderPoints[2*(cavityIndex-2)]-topBottomThickness)*scale;
else if (latNumber== (cavityIndex+cavityHeight-2)) h=(cylinderPoints[2*(cavityIndex+cavityHeight+2)]+topBottomThickness)*scale;
else h= (((cylinderPoints[2*(cavityIndex-2)]-topBottomThickness)*scale)* (cavityIndex+cavityHeight-3-latNumber)+
((cylinderPoints[2*(cavityIndex+cavityHeight+2)]+topBottomThickness)*scale)* (latNumber-(cavityIndex+3)))/(cavityHeight-6);
}
var sinPhi = Math.sin(phi);
var cosPhi = Math.cos(phi);
var x = cosPhi * r;
var y = h;
var z = sinPhi * r;
textureCoordData.push(u);
textureCoordData.push(v);
vertexPositionData.push(x);
vertexPositionData.push(y);
vertexPositionData.push(z);
}
}
// Handling normalData - average normals connected to the vertex, proportionally to the angles of the triangles connected to it (if it is non-zero)
// even different - angle*area, so for the smooth rectangular mesh there will be the same contribution for the "90-degree" and a pair of the "45-degree" ones
var normalData = Array(vertexPositionData.length);
var normalMaxSize = Array(vertexPositionData.length/3);
for (var i=0;i<normalMaxSize.length;i++) normalMaxSize[i]=0;
for (var i=0;i<normalData.length;i++) normalData[i]=0;
var indexData = [];
for (var latNumber = 0; latNumber < latitudeBands; latNumber++) {
for (var longNumber = 0; longNumber < longitudeBands; longNumber++) {
var first = (latNumber * (longitudeBands + 1)) + longNumber;
var second = first + longitudeBands + 1;
// Split quadrilateral into 2 triangles so the total area will be minimal
var F =[vertexPositionData[3*first+0], vertexPositionData[3*first+1], vertexPositionData[3*first+2]];
var S =[vertexPositionData[3*second+0],vertexPositionData[3*second+1],vertexPositionData[3*second+2]];
var F1=[vertexPositionData[3*first+3], vertexPositionData[3*first+4], vertexPositionData[3*first+5]];
var S1=[vertexPositionData[3*second+3],vertexPositionData[3*second+4],vertexPositionData[3*second+5]];
var SF= [S[0]- F[0], S[1]- F[1], S[2]- F[2]];
var F1F= [F1[0]- F[0], F1[1]- F[1], F1[2]- F[2]];
var S1S= [S1[0]- S[0], S1[1]- S[1], S1[2]- S[2]];
var S1F1=[S1[0]-F1[0], S1[1]-F1[1], S1[2]-F1[2]];
var nFSF1= vmul(SF,F1F);
var nSS1F1= vmul(S1F1,S1S);
var nFSS1= vmul(SF,S1S);
var nFS1F1= vmul(S1F1,F1F);
var aFSF1= abs3(nFSF1);
var aSS1F1= abs3(nSS1F1);
var aFSS1= abs3(nFSS1);
var aFS1F1= abs3(nFS1F1);
var vIndices, normals, areas, vIndex;
if ((aFSF1+aSS1F1)>(aFSS1+aFS1F1)){
vIndices= [[first,second+1,first+1],[first,second,second+1]];
normals=[unityVector3(nFS1F1),unityVector3(nFSS1)];
areas= [aFS1F1,aFSS1];
} else {
vIndices= [[first,second,first+1],[second,second+1,first+1]];
normals=[unityVector3(nFSF1),unityVector3(nSS1F1)];
areas=[aFSF1,aSS1F1];
}
for (var i=0;i<2;i++) {
if (areas[i]>0.0) for (var j=0;j<3;j++) {
indexData.push(vIndices[i][j]);
}
}
for (var i=0;i<2;i++) if (areas[i]>0) for (var j=0;j<3;j++) {
var indx0=vIndices[i][j];
var indx1=vIndices[i][(j+1)%3];
var indx2=vIndices[i][(j+2)%3];
var l1=abs3([vertexPositionData[3*indx1+0]-vertexPositionData[3*indx0+0],
vertexPositionData[3*indx1+1]-vertexPositionData[3*indx0+1],
vertexPositionData[3*indx1+2]-vertexPositionData[3*indx0+2]]);
var l2=abs3([vertexPositionData[3*indx2+0]-vertexPositionData[3*indx0+0],
vertexPositionData[3*indx2+1]-vertexPositionData[3*indx0+1],
vertexPositionData[3*indx2+2]-vertexPositionData[3*indx0+2]]);
var sinAngle=areas[i]/l1/l2;
if (sinAngle>1.0) sinAngle=1.0;
else if (sinAngle<-1.0) sinAngle=-1.0;
var angle=Math.abs(Math.asin(sinAngle)); // Do we need Math.abs() nere?
var w=angle*areas[i];
normalData[3*indx0+0]-=normals[i][0]*w;
normalData[3*indx0+1]-=normals[i][1]*w;
normalData[3*indx0+2]-=normals[i][2]*w;
}
}
}
for (var i=0; i<normalData.length; i+=3) {
var v=[normalData[i],normalData[i+1],normalData[i+2]];
var l=abs3(v);
for (var j=i; j<i+3;j++) normalData[j]/=l;
}
//document.title="indexData.length="+indexData.length;
eyesisVertexNormalBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, eyesisVertexNormalBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(normalData), gl.STATIC_DRAW);
eyesisVertexNormalBuffer.itemSize = 3;
eyesisVertexNormalBuffer.numItems = normalData.length / 3;
eyesisVertexTextureCoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, eyesisVertexTextureCoordBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoordData), gl.STATIC_DRAW);
eyesisVertexTextureCoordBuffer.itemSize = 2;
eyesisVertexTextureCoordBuffer.numItems = textureCoordData.length / 2;
eyesisVertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, eyesisVertexPositionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexPositionData), gl.STATIC_DRAW);
eyesisVertexPositionBuffer.itemSize = 3;
eyesisVertexPositionBuffer.numItems = vertexPositionData.length / 3;
eyesisVertexIndexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, eyesisVertexIndexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indexData), gl.STREAM_DRAW);
eyesisVertexIndexBuffer.itemSize = 1;
eyesisVertexIndexBuffer.numItems = indexData.length;
}
var sunVertexPositionBuffer;
var sunVertexNormalBuffer;
var sunVertexTextureCoordBuffer;
var sunVertexIndexBuffer;
function initBuffersSun() {
var sunRays = 16;
var sunRaysLength=15; // relative to the Sun radius
var sunRaysWidth=0.4; // relative ray period
var radius = worldRadius*16.0*Math.PI/180/60; // 16' (angular minutes)
var rayRadius=sunRaysLength*radius;
var vertexPositionData = Array (3*(3*sunRays+1));
var normalData = Array(vertexPositionData.length);
var textureCoordData = Array (2*(3*sunRays+1));
var indexData = Array (3*3*sunRays);
vertexPositionData[0]=0;
vertexPositionData[1]=0;
vertexPositionData[2]=0;
textureCoordData[0]=0.5;
textureCoordData[1]=0.5;
for (var rayNumber=0;rayNumber<sunRays;rayNumber++) {
var phi0 = rayNumber * 2 * Math.PI / sunRays;
var phi1 = phi0+ sunRaysWidth* 2 * Math.PI / sunRays;
var phi2 = phi0+ sunRaysWidth* Math.PI / sunRays;
vertexPositionData[3*(2*rayNumber+1)+0]=radius*Math.cos(phi0);
vertexPositionData[3*(2*rayNumber+1)+1]=radius*Math.sin(phi0);
vertexPositionData[3*(2*rayNumber+1)+2]=0;
vertexPositionData[3*(2*rayNumber+2)+0]=radius*Math.cos(phi1);
vertexPositionData[3*(2*rayNumber+2)+1]=radius*Math.sin(phi1);
vertexPositionData[3*(2*rayNumber+2)+2]=0;
vertexPositionData[3*(2*sunRays+rayNumber+1)+0]= rayRadius*Math.cos(phi2);
vertexPositionData[3*(2*sunRays+rayNumber+1)+1]= rayRadius*Math.sin(phi2);
vertexPositionData[3*(2*sunRays+rayNumber+1)+2]=0;
textureCoordData[2*(2*rayNumber+1)+0]=0.25*(2+Math.cos(phi0));
textureCoordData[2*(2*rayNumber+1)+1]=0.25*(2+Math.sin(phi0));
textureCoordData[2*(2*rayNumber+2)+0]=0.25*(2+Math.cos(phi1));
textureCoordData[2*(2*rayNumber+2)+1]=0.25*(2+Math.sin(phi1));
textureCoordData[2*(2*sunRays+rayNumber+1)+0]= 0.5*(1+Math.cos(phi2));
textureCoordData[2*(2*sunRays+rayNumber+1)+1]= 0.5*(1+Math.sin(phi2));
}
for (var i=0; i<(3*sunRays+1);i++) {
normalData[3*i ]=0.0;
normalData[3*i+1]=0.0;
normalData[3*i+2]=1.0;
}
// for (var i =0; i<2*sunRays; i++) if ((i%2)==0) {
for (var i =0; i<2*sunRays; i++) {
indexData[3*i ]=0; // center point
indexData[3*i+1]=i+1;
indexData[3*i+2]=(i==(2*sunRays-1))?1:(i+2);
}
for (var i =0; i<sunRays; i++) {
// for (var i =0; i<1; i++) {
indexData[3*(i+2*sunRays) ]=2*i+2;
indexData[3*(i+2*sunRays)+1]=2*i+1;
indexData[3*(i+2*sunRays)+2]=i+2*sunRays+1;
}
sunVertexNormalBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, sunVertexNormalBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(normalData), gl.STATIC_DRAW);
sunVertexNormalBuffer.itemSize = 3;
sunVertexNormalBuffer.numItems = normalData.length / 3;
sunVertexTextureCoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, sunVertexTextureCoordBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoordData), gl.STATIC_DRAW);
sunVertexTextureCoordBuffer.itemSize = 2;
sunVertexTextureCoordBuffer.numItems = textureCoordData.length / 2;
sunVertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, sunVertexPositionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexPositionData), gl.STATIC_DRAW);
sunVertexPositionBuffer.itemSize = 3;
sunVertexPositionBuffer.numItems = vertexPositionData.length / 3;
sunVertexIndexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, sunVertexIndexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indexData), gl.STREAM_DRAW);
sunVertexIndexBuffer.itemSize = 1;
sunVertexIndexBuffer.numItems = indexData.length;
}
var footprintsBackpackVertexPositionBuffer;
var footprintsBackpackVertexNormalBuffer;
var footprintsBackpackVertexTextureCoordBuffer;
var footprintsBackpackVertexIndexBuffer;
// just a circle
function initBuffersFootprintsBackpack(radius) {
var segments = 32;
var vertexPositionData = Array (3*(segments+1));
var normalData = Array(vertexPositionData.length);
var textureCoordData = Array (2*(segments+1));
var indexData = Array (3*segments);
vertexPositionData[0]=0;
vertexPositionData[1]=0;
vertexPositionData[2]=0;
textureCoordData[0]=0.5;
textureCoordData[1]=0.5;
for (var segmentNumber=0;segmentNumber<segments;segmentNumber++) {
var phi = segmentNumber * 2 * Math.PI / segments;
var cosPhi=Math.cos(phi);
var sinPhi=Math.sin(phi);
vertexPositionData[3*(segmentNumber+1)+2]=radius*cosPhi;
vertexPositionData[3*(segmentNumber+1)+0]=radius*sinPhi;
vertexPositionData[3*(segmentNumber+1)+1]=0;
textureCoordData[2*(segmentNumber+1)+0]=0.5*(1+cosPhi);
textureCoordData[2*(segmentNumber+1)+1]=0.5*(1+sinPhi);
}
for (var i=0; i<(segments+1);i++) {
normalData[3*i ]=0.0;
normalData[3*i+1]=1.0;
normalData[3*i+2]=0.0;
}
for (var i =0; i<segments; i++) {
indexData[3*i ]=0; // center point
indexData[3*i+1]=i+1;
indexData[3*i+2]=(i==(segments-1))?1:(i+2);
}
footprintsBackpackVertexNormalBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, footprintsBackpackVertexNormalBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(normalData), gl.STATIC_DRAW);
footprintsBackpackVertexNormalBuffer.itemSize = 3;
footprintsBackpackVertexNormalBuffer.numItems = normalData.length / 3;
footprintsBackpackVertexTextureCoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, footprintsBackpackVertexTextureCoordBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoordData), gl.STATIC_DRAW);
footprintsBackpackVertexTextureCoordBuffer.itemSize = 2;
footprintsBackpackVertexTextureCoordBuffer.numItems = textureCoordData.length / 2;
footprintsBackpackVertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, footprintsBackpackVertexPositionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexPositionData), gl.STATIC_DRAW);
footprintsBackpackVertexPositionBuffer.itemSize = 3;
footprintsBackpackVertexPositionBuffer.numItems = vertexPositionData.length / 3;
footprintsBackpackVertexIndexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, footprintsBackpackVertexIndexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indexData), gl.STREAM_DRAW);
footprintsBackpackVertexIndexBuffer.itemSize = 1;
footprintsBackpackVertexIndexBuffer.numItems = indexData.length;
}
function drawScene() {
if (currentTextureNumber<0) {
// document.title="too early to drawScene() - texture not set yet";
return;
}
var newRotationMatrix = createRotationMatrix(elevation, [1, 0, 0]);
viewRotationMatrix = newRotationMatrix.x(createRotationMatrix(azimuth, [0, 1, 0]));
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
perspective (fovY, gl.viewportWidth / gl.viewportHeight, znear, zfar);
gl.uniform1i(shaderProgram.useLightingUniform, false);
// drawSun();
if (editEnabled && (previousTextureNumber>=0) && (settings.seethrough<1.0)) {
drawPanorama(panoramaRotationMatrix,currentTextureNumber,1.0-settings.seethrough);
drawPanorama(previousPanoramaRotationMatrix,previousTextureNumber,settings.seethrough);
} else {
if (transitionSeeThrough>0.0) {
drawPanorama(panoramaRotationMatrix,currentTextureNumber,1.0-transitionSeeThrough);
drawPanorama(previousPanoramaRotationMatrix,previousTextureNumber,transitionSeeThrough);
} else drawPanorama(panoramaRotationMatrix,currentTextureNumber,1.0);
}
drawSun();
drawArrowsAndCams();
locateArrows();
showPlanView(document.getElementById("idShowPlan").checked || (floatingEyesisNum>=0));
sceneDrawn=true;
clearInterval(loading_intvl);
$("#status").hide();
createPermanentLink();
}
function drawArrowsAndCams() {
if (showArrows) {
for (var i=1;i<arrows.length;i++) {
//if (arrows.length>map.length) alert(map.length+" "+arrows.length);
var visibility=settings.markVisibility3d?(map[i].open!==false):(map[i].visibility!==false);
var type=(settings.edit || (map[i].open!==false))?arrows[i].type:'a';
drawArrow(arrows[i].angle,arrows[i].down,arrows[i].distance, type, visibility?((i==floatingEyesisNum)?1:0):3, i); // mode - 0-normal, 1 - "ghost", 2 - selected, last map number, 3 - invisible (visibility=0)
}
if (floatingEyesisNum>=0) drawArrow(floatingEyesis.angle,floatingEyesis.down,floatingEyesis.distance, "c", 2, floatingEyesisNum);
}
if (showArrows) {
showMenus();
}else{
hideMenus();
}
//oleg
if (editEnabled) {
drawLine($V([1,0,0,0]),0,0.0,0.5,dotVertexPositionBuffer); // horizontal
drawLine($V([0,1,0,0]),0,0.0,0.5,dotVertexPositionBuffer2);// vertical
}
}
//transitionSeeThrough
function drawPanorama(rotationMatrix,textureNumber,opacity) {
loadIdentity();
multMatrix(viewRotationMatrix);
multMatrix(rotationMatrix);
setMatrixUniforms();
if (opacity<1.0) {
gl.uniform1f(shaderProgram.alphaUniform, opacity);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
gl.enable(gl.BLEND);
gl.disable(gl.DEPTH_TEST);
gl.uniform1f(shaderProgram.alphaUniform, opacity);
} else {
gl.uniform1f(shaderProgram.alphaUniform, 1.0);
gl.disable(gl.BLEND);
gl.enable(gl.DEPTH_TEST);
gl.uniform1f(shaderProgram.alphaUniform, 1.0);
}
//if (typeof(panoTextures[currentTextureNumber])=='undefined') document.title+=" "+currentTextureNumber+" - undefined!";
for (var subtexture=0;subtexture<numSubTextures;subtexture++){
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, panoTextures[textureNumber][subtexture]);
gl.uniform1i(shaderProgram.samplerUniform, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, panoVertexPositionBuffer[subtexture]);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, panoVertexPositionBuffer[subtexture].itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, panoVertexTextureCoordBuffer[subtexture]);
gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, panoVertexTextureCoordBuffer[subtexture].itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, panoVertexNormalBuffer[subtexture]);
gl.vertexAttribPointer(shaderProgram.vertexNormalAttribute, panoVertexNormalBuffer[subtexture].itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, panoVertexIndexBuffer[subtexture]);
gl.drawElements(gl.TRIANGLES, panoVertexIndexBuffer[subtexture].numItems, gl.UNSIGNED_SHORT, 0);
}
}
var sunRotationMatrix3x3;
function drawSun() {
loadIdentity();
multMatrix(viewRotationMatrix);
multMatrix(createRotationMatrix(-Sun.azimuth, [0, 1, 0]));
multMatrix(createRotationMatrix(Sun.elevation, [1, 0, 0]));
Sun.unitVector=mvMatrix.make3x3().x(Vector.create([0,0,-1]));
mvTranslate([0.0, 0.0, -0.9*worldRadius]);
setMatrixUniforms();
gl.uniform1f(shaderProgram.alphaUniform, 1.0);
gl.disable(gl.BLEND);
gl.enable(gl.DEPTH_TEST);
gl.bindTexture(gl.TEXTURE_2D, sunTexture);
gl.uniform1i(shaderProgram.samplerUniform, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, sunVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, sunVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, sunVertexTextureCoordBuffer);
gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, sunVertexTextureCoordBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, sunVertexNormalBuffer);
gl.vertexAttribPointer(shaderProgram.vertexNormalAttribute, sunVertexNormalBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, sunVertexIndexBuffer);
gl.drawElements(gl.TRIANGLES, sunVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
// gl.drawElements(gl.LINE_STRIP, sunVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
}
function drawArrow(angle,down, distance, type,mode, mapNumber) { // mode=0 - normal, mode 1 - eyesis "ghost", mode 2 - moving eyesis, 3 - "invisible"
var isEyesis= (type=="c") || (mode!=0); // isn't (type=="c") enough?
// Set lighting
gl.uniform1i(shaderProgram.useLightingUniform, isEyesis);
if (isEyesis) {
var directionalRGB= [Sun.directionalRGB[0]*Sun.fraction, Sun.directionalRGB[1]*Sun.fraction, Sun.directionalRGB[2]*Sun.fraction];
var ambientRGB=[Sun.ambientRGB[0]*(1.0-Sun.fraction),Sun.ambientRGB[0]*(1.0-Sun.fraction),Sun.ambientRGB[0]*(1.0-Sun.fraction)];
gl.uniform3f(shaderProgram.ambientColorUniform, ambientRGB[0],ambientRGB[1],ambientRGB[1]);
var lightingDirection = Sun.unitVector;
var adjustedLD = lightingDirection.toUnitVector();
var flatLD = adjustedLD.flatten();
gl.uniform3f( shaderProgram.lightingDirectionUniform, flatLD[0], flatLD[1], flatLD[2] );
gl.uniform3f( shaderProgram.directionalColorUniform, directionalRGB[0],directionalRGB[1],directionalRGB[2]);
}
loadIdentity();
multMatrix(viewRotationMatrix);
if (!isEyesis) {
multMatrix(createRotationMatrix(angle, [0, 1, 0]));
mvTranslate([0.0, -down, -Math.abs(distance)]);
setMatrixUniforms();
gl.uniform1f(shaderProgram.alphaUniform, 1.0);
gl.disable(gl.BLEND);
gl.enable(gl.DEPTH_TEST);
gl.uniform1f(shaderProgram.alphaUniform, 1.0);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, arrowTexture);
gl.uniform1i(shaderProgram.samplerUniform, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, arrowVertexTextureCoordBuffer);
gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, arrowVertexTextureCoordBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, arrowVertexNormalBuffer);
gl.vertexAttribPointer(shaderProgram.vertexNormalAttribute, arrowVertexNormalBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, arrowVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, arrowVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, arrowVertexIndexBuffer);
gl.drawElements(gl.TRIANGLES, arrowVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
} else {
// should just move, no rotaion
// Show Eyesis camera
if (((mode>0) && (mode!=3)) || showCams) {
var arad=angle*Math.PI/180;
mvTranslate([-Math.abs(distance)*Math.sin(arad), -down, -Math.abs(distance)*Math.cos(arad)]);
// multMatrix(createRotationMatrix( -map[mapNumber].heading, [0, 1, 0])); /// TODO: add/subtract cameraHeading?
multMatrix(createRotationMatrix( -(map[mapNumber].heading- map[mapNumber].cameraHeading), [0, 1, 0]));
multMatrix(createRotationMatrix( map[mapNumber].tilt-90, [1, 0, 0]));
multMatrix(createRotationMatrix( map[mapNumber].roll, [0, 0, 1]));
multMatrix(createRotationMatrix( 90, [0, 1, 0])); // does nothing visible
setMatrixUniforms();
if (mode==0) {
gl.uniform1f(shaderProgram.alphaUniform, 1.0);
gl.disable(gl.BLEND);
gl.enable(gl.DEPTH_TEST);
gl.uniform1f(shaderProgram.alphaUniform, 1.0);
} else if ((mode==1) || (mode==3)) {
gl.uniform1f(shaderProgram.alphaUniform, 0.5);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
gl.enable(gl.BLEND);
gl.disable(gl.DEPTH_TEST);
gl.uniform1f(shaderProgram.alphaUniform, 0.5);
} else {
gl.uniform1f(shaderProgram.alphaUniform, 0.8);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
gl.enable(gl.BLEND);
gl.disable(gl.DEPTH_TEST);
gl.uniform1f(shaderProgram.alphaUniform, 0.8);
}
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, eyesisTexture[mode]);
gl.uniform1i(shaderProgram.samplerUniform, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, eyesisVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, eyesisVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, eyesisVertexTextureCoordBuffer);
gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, eyesisVertexTextureCoordBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, eyesisVertexNormalBuffer);
gl.vertexAttribPointer(shaderProgram.vertexNormalAttribute, eyesisVertexNormalBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, eyesisVertexIndexBuffer);
gl.drawElements(gl.TRIANGLES, eyesisVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
}
// show footprints
if ((map[mapNumber].cameraType=="eyesis_backpack") || (map[mapNumber].cameraType=="eyesis_tripod")) {
// console.log("Show footprints: aboveGround="+map[mapNumber].aboveGround+" cameraType="+map[mapNumber].cameraType+" mapNumber="+mapNumber+" mode="+mode);
//document.title="eyesis_backpack"+mapNumber;
loadIdentity();
multMatrix(viewRotationMatrix);
var arad=angle*Math.PI/180;
mvTranslate([-Math.abs(distance)*Math.sin(arad), -(down+ map[mapNumber].aboveGround), -Math.abs(distance)*Math.cos(arad)]);
multMatrix(createRotationMatrix( -(map[mapNumber].heading- map[mapNumber].cameraHeading), [0, 1, 0]));
// multMatrix(createRotationMatrix( map[mapNumber].tilt-90, [1, 0, 0]));
// multMatrix(createRotationMatrix( map[mapNumber].roll, [0, 0, 1]));
multMatrix(createRotationMatrix( 90, [0, 1, 0]));
setMatrixUniforms();
if (mode==0) {
gl.uniform1f(shaderProgram.alphaUniform, 1.0);
gl.disable(gl.BLEND);
gl.enable(gl.DEPTH_TEST);
gl.uniform1f(shaderProgram.alphaUniform, 1.0);
} else if (mode==1) {
gl.uniform1f(shaderProgram.alphaUniform, 0.5);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
gl.enable(gl.BLEND);
gl.disable(gl.DEPTH_TEST);
gl.uniform1f(shaderProgram.alphaUniform, 0.5);
} else {
gl.uniform1f(shaderProgram.alphaUniform, 0.8);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
gl.enable(gl.BLEND);
gl.disable(gl.DEPTH_TEST);
gl.uniform1f(shaderProgram.alphaUniform, 0.8);
}
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, footprintsBackpackTexture[mode]);
gl.uniform1i(shaderProgram.samplerUniform, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, footprintsBackpackVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, footprintsBackpackVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, footprintsBackpackVertexTextureCoordBuffer);
gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, footprintsBackpackVertexTextureCoordBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, footprintsBackpackVertexNormalBuffer);
gl.vertexAttribPointer(shaderProgram.vertexNormalAttribute, footprintsBackpackVertexNormalBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, footprintsBackpackVertexIndexBuffer);
gl.drawElements(gl.TRIANGLES, footprintsBackpackVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
}// else console.log("Dop not show footprints: aboveGround="+map[mapNumber].aboveGround+" cameraType="+map[mapNumber].cameraType+" mapNumber="+mapNumber+" mode="+mode);
}
}
var labelHeight=16;
var labelWidth=36;
function locateArrows() {
arrowsVisible=Array(arrows.length);
arrowsXY= Array(arrows.length);
var id;
var innerHTML="";
var labelMaxX=gl.viewportWidth-labelWidth/2; // to prevent labels leave the canvas (and cause scrollbars)
var labelMaxY=gl.viewportHeight-labelHeight/2;
arrowsVisible[0]=false; // just in case
var hotSpotBelow=!showCams || (typeof(clickCams)=='undefined') || !clickCams;
for (var i=1;i<arrows.length;i++) {
loadIdentity();
multMatrix(pMatrix);
mvTranslate([0.0, 0, -2.0*znear]); // This I do not understand, but it (moving projection plane on the other side of the viewer) works. AF
multMatrix(viewRotationMatrix);
multMatrix(createRotationMatrix(arrows[i].angle, [0, 1, 0]));
// make hotspot at the footsteps, not at the camera
if ((arrows[i].type=='c') && ((map[i].cameraType=="eyesis_backpack") || (map[i].cameraType=="eyesis_tripod")) && hotSpotBelow) { // or some other?
mvTranslate([0.0, -(arrows[i].down+map[i].aboveGround), -Math.abs(arrows[i].distance)]);
} else {
mvTranslate([0.0, -arrows[i].down, -Math.abs(arrows[i].distance)]);
}
arrowsVisible[i]=(mvMatrix.elements[2][3]>0.0); // other side - both mvMatrix.elements[2][3] and mvMatrix.elements[3][3] are negative
if (arrowsVisible[i]) {
arrowsXY[i]={x:Math.round(0.5*(1.0+(mvMatrix.elements[0][3]/mvMatrix.elements[2][3]))*gl.viewportWidth), // too fast for close obj, good for arrows
y:Math.round(0.5*(1.0-(mvMatrix.elements[1][3]/mvMatrix.elements[2][3]))*gl.viewportHeight)};
if (settings.labels && showArrows && (arrowsXY[i].x<labelMaxX) && (arrowsXY[i].y<labelMaxY)) {
id="idTarget"+((i<10)?"0":"")+i;
var ts="";
// if (typeof(map[i].description)!='undefined') ts+=map[i].description+" ";
// else if (typeof(map[i].name)!='undefined') ts+=map[i].name+" ";
if (typeof(map[i].name)!='undefined') ts+=map[i].name+" - ";
if (typeof(map[i].description)!='undefined') ts+=map[i].description+" ";
ts+=map[i].time.hour+":"+map[i].time.minute+":"+Math.round(map[i].time.second*10)/10;
var visibility=settings.markVisibility3d?(map[i].open!==false):(map[i].visibility!==false);
var color=visibility?"#ffdddd":"#668888";
innerHTML+='<div id="'+id+'" style="position:absolute;text-align:center;font-size:12px;width:'+labelWidth+'px;height:'+labelHeight+'px;left:'+(arrowsXY[i].x-labelWidth/2)+'px;top:'+(arrowsXY[i].y-labelHeight/2)+'px;'+
'background-color:#ffffff;" title="'+ts+'" '+
'ondragstart = "cancellingEventHandler()" ondraggesture="cancellingEventHandler()" onselectstart="cancellingEventHandler()" '+
'onmousedown="clickedLabel(event,'+i+');"'+
'>'+(Math.round(10*Math.abs(map[i].distance))/10)+'m</div>';
}
}
}
if (floatingEyesisNum>=0) {
loadIdentity();
multMatrix(pMatrix);
multMatrix(viewRotationMatrix);
multMatrix(createRotationMatrix(floatingEyesis.angle, [0, 1, 0]));
if ((map[floatingEyesisNum].cameraType=="eyesis_backpack") || (map[floatingEyesisNum].cameraType=="eyesis_tripod") ) { // or some other? eyesis_tripod
mvTranslate([0.0, -(floatingEyesis.down+map[floatingEyesisNum].aboveGround), -Math.abs(floatingEyesis.distance)]);
} else {
mvTranslate([0.0, -floatingEyesis.down, -Math.abs(floatingEyesis.distance)]);
}
floatingEyesisVisible=(mvMatrix.elements[2][3]>0.0); // other side - both mvMatrix.elements[2][3] and mvMatrix.elements[3][3] are negative
if (floatingEyesisVisible) {
floatingEyesisXY=[Math.round(0.5*(1.0+(mvMatrix.elements[0][3]/mvMatrix.elements[2][3]))*gl.viewportWidth),
Math.round(0.5*(1.0-(mvMatrix.elements[1][3]/mvMatrix.elements[2][3]))*gl.viewportHeight)];
if (settings.labels && showArrows) {
id="idTarget00";
var ts="";
// if (typeof(map[floatingEyesisNum].description)!='undefined') ts+=map[floatingEyesisNum].description+' ';
// else if (typeof(map[floatingEyesisNum].name)!='undefined') ts+=map[floatingEyesisNum].name+' ';
if (typeof(map[floatingEyesisNum].name)!='undefined') ts+=map[floatingEyesisNum].name+" - ";
if (typeof(map[floatingEyesisNum].description)!='undefined') ts+=map[floatingEyesisNum].description+" ";
ts+=map[floatingEyesisNum].time.hour+":"+map[floatingEyesisNum].time.minute+":"+Math.round(map[floatingEyesisNum].time.second*10)/10;
innerHTML+='<div id="'+id+'" style="position:absolute;text-align:center;font-size:12px;width:'+labelWidth+'px;height:'+labelHeight+'px;left:'+(floatingEyesisXY[0]-labelWidth/2)+'px;top:'+(floatingEyesisXY[1]-labelHeight/2)+'px;'+
'background-color:#ffbbbb;" title="'+ts+'" '+
'ondragstart = "cancellingEventHandler()" ondraggesture="cancellingEventHandler()" onselectstart="cancellingEventHandler()" '+
'onmousedown="clickedLabel(event,'+0+');"'+
'>'+(Math.round(10*Math.abs(floatingEyesis.distance))/10)+'m</div>';
}
}
}
document.getElementById("idLabels").innerHTML=innerHTML;
}
// subs
function vmul(a,b) {
return [a[1]*b[2]-a[2]*b[1], a[2]*b[0]-a[0]*b[2], a[0]*b[1]-a[1]*b[0]];
}
function area(a,b) {
var v=vmul(a,b);
return Math.sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
}
function abs3(v) {
return Math.sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
}
function unityVector3(v) {
l=Math.sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
if (l==0) return [0,0,0];
else return [v[0]/l,v[1]/l,v[2]/l];
}
var mvMatrix;
var mvMatrixStack = [];
function mvPushMatrix(m) {
if (m) {
mvMatrixStack.push(m.dup());
mvMatrix = m.dup();
} else {
mvMatrixStack.push(mvMatrix.dup());
}
}
function mvPopMatrix() {
if (mvMatrixStack.length == 0) {
throw "Invalid popMatrix!";
}
mvMatrix = mvMatrixStack.pop();
return mvMatrix;
}
function loadIdentity() {
mvMatrix = Matrix.I(4);
}
function multMatrix(m) {
mvMatrix = mvMatrix.x(m);
}
function mvTranslate(v) {
var m = Matrix.Translation($V([v[0], v[1], v[2]])).ensure4x4();
multMatrix(m);
}
function createRotationMatrix(angle, v) {
var arad = angle * Math.PI / 180.0;
return Matrix.Rotation(arad, $V([v[0], v[1], v[2]])).ensure4x4();
}
function mvRotate(angle, v) {
multMatrix(createRotationMatrix(angle, v));
}
var pMatrix;
function perspective(fovy, aspect, znear, zfar) {
pMatrix = makePerspective(fovy, aspect, znear, zfar);
}
function setMatrixUniforms() {
gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, new Float32Array(pMatrix.flatten()));
gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, new Float32Array(mvMatrix.flatten()));
var normalMatrix = mvMatrix.inverse();
normalMatrix = normalMatrix.transpose();
gl.uniformMatrix4fv(shaderProgram.nMatrixUniform, false, new Float32Array(normalMatrix.flatten()));
}
<html>
<head>
<title>Elphel Panorama Index</title>
<script src="files/jquery-1.6.4.min.js"></script>
<script src="files/useful_functions.js"></script>
<script src="files/pano_index.js"></script>
<link href="files/button.css" rel="stylesheet" type="text/css">
<link href="files/pano_index.css" rel="stylesheet" type="text/css">
<style>
</style>
</head>
<body>
<h3>Elphel Panorama Routes Index</h3>
<div id=main >
<div id='route_list'>
</div>
<div id='action_list'>
<div id='action_form' >
New copy name: <input type=text id=input_fn class="input_text" />
<button id=do_things onclick="create_copy()" >Create Editable Copy</button>
</div>
<div id=status_box>
Status:&nbsp;<input type=text id=status class="input_text" disabled />
</div>
</div>
</div>
<script>
postRequest("GetRoutesAndKMLs", "");
</script>
</body>
</html>
\ No newline at end of file
<?php
/********************************************************************************
*! FILE NAME : map_pano.php
*! DESCRIPTION: db / file multiplexor
*! VERSION: 1.0
*! AUTHOR: Oleg Dzhimiev <oleg@elphel.com>
*! Copyright (C) 2011 Elphel, Inc
*! -----------------------------------------------------------------------------**
*! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! The four essential freedoms with GNU GPL software:
*! * the freedom to run the program for any purpose
*! * the freedom to study how the program works and change it to make it do what you wish
*! * the freedom to redistribute copies so you can help your neighbor
*! * the freedom to distribute copies of your modified versions to others
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------**
*! $Log: map_pano.php,v $
*!
*/
require_once("call_filter.php");
if (isset($_GET['kml'])) {
if (is_file("kml_files/".$_GET['kml'])) require("map_pano_file.php");
else require("map_pano_db.php");
}else{
echo "Hahaha, well";
}
?>
<?php
/********************************************************************************
*! FILE NAME : map_pano_db.php
*! DESCRIPTION: original file
*! VERSION: 1.0
*! AUTHOR:
*! Copyright (C) 2011 Elphel, Inc
*! -----------------------------------------------------------------------------**
*! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! The four essential freedoms with GNU GPL software:
*! * the freedom to run the program for any purpose
*! * the freedom to study how the program works and change it to make it do what you wish
*! * the freedom to redistribute copies so you can help your neighbor
*! * the freedom to distribute copies of your modified versions to others
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------**
*! $Log: map_pano_db.php,v $
*!
*/
require_once("call_filter.php");
include("pano_db_functions.php");
ConnectMySQL();
if (isset($_GET['kml'])) {
$RouteID = $_GET['kml'];
if ($_GET['map'] == "all") {
$RouteData = GetNodesByRoute($RouteID);
$kml = "";
foreach ($RouteData as $Node) {
$kml .= CreateKMLEntry($Node);
}
PrintKML($kml);
}
if (isset($_GET['href'])) {
$kml = "";
$href = $_GET['href'];
$nodeID = GetNodeIDbyImageFileName($RouteID, $href);
$startnode = GetNodeData($nodeID['id']);
$kml = CreateKMLEntry($startnode);
$range = $_GET['range'];
$earthRadius = 6378100; // meters
$onelatitudedegree = 111110; // we assume one latitude degree is 111,110 meters everywhere on earth
$LatMin = $startnode['Latitude'] - (($range / $onelatitudedegree) / 2);
$LatMax = $startnode['Latitude'] + (($range / $onelatitudedegree) / 2);
/*
echo "delta_long: ".(($range / $onelatitudedegree) / 2)." | ";
echo "lat: ".$startnode['Latitude']." | ";
echo "long: ".$startnode['Longitude']." | ";
echo "LatMax: ".$LatMax." | ";
echo "LatMin: ".$LatMin." | ";
*/
//longitude
// lat 0° = 111,320m
// lat 10° = 109,640m
// lat 20° = 104,650m
// lat 30° = 96,490m
// lat 40° = 85,390m
// lat 50° = 71,700m
// lat 60° = 55,800m
// lat 70° = 38,190m
// lat 80° = 19,390m
// lat 90° = 0m
$delta_long = cos($startnode['Latitude']) * $range / $onelatitudedegree; // this is a greatly simplified but still pretty accurate model
$LongMin = $startnode['Longitude'] - ($delta_long / 2);
$LongMax = $startnode['Longitude'] + ($delta_long / 2);
//$RouteData_pre = GetNodesAt($LatMin, $LatMax, $LongMin, $LongMax);
$RouteData = GetNodesAt($LatMin, $LatMax, $LongMin, $LongMax);
//$RouteData = GetNodesAt($startnode['Latitude'], $startnode['Latitude'], $startnode['Longitude'], $startnode['Longitude']);
if (count($RouteData) > 0) {
foreach ($RouteData as $Node) {
if ($Node['ID']!=$startnode['ID']) $kml .= CreateKMLEntry($Node);
}
PrintKML($kml);
}
/*$d1 = acos(sin(lat1)*sin(lat2) + cos(lat1)*cos(lat2)) * $earthRadius;
$d1 = acos(sin(lat1)*sin(lat1) + cos(lat1)*cos(lat1) * cos(lon2-lon1)) * $earthRadius;*/
}
}
?>
\ No newline at end of file
<?php
/********************************************************************************
*! FILE NAME : map_pano_file.php
*! DESCRIPTION: original file
*! VERSION: 1.0
*! AUTHOR:
*! Copyright (C) 2011 Elphel, Inc
*! -----------------------------------------------------------------------------**
*! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! The four essential freedoms with GNU GPL software:
*! * the freedom to run the program for any purpose
*! * the freedom to study how the program works and change it to make it do what you wish
*! * the freedom to redistribute copies so you can help your neighbor
*! * the freedom to distribute copies of your modified versions to others
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------**
*! $Log: map_pano_file.php,v $
*!
*/
require_once("call_filter.php");
$kmlFile="";
require "pano.inc";
$latitude="";
$longitude="";
$href="";
$range=0;
$maskFile="";
$fullMap=false;
$interpolate=false;
$allNodes=false; // include those with visibility=0
$generateVisibility3d=false;
$applyVisibility3d=true;
$interpolateRange=false;
$ohref="";
$corrAlt=0;
$corrLat=0;
$corrLon=0;
$forceViewMode=false;
$protoFile="";
$relative2kml=false; // relative path to images - false - from this script, true - from kml
$kmlValid=false;
if (isset($_GET['latitude'])) $latitude=$_GET['latitude'];
if (isset($_GET['longitude'])) $longitude=$_GET['longitude'];
if (isset($_GET['href'])) $href=urldecode($_GET['href']); // right side of the image url (will compare only this long, prefix may be ommitted)
if (isset($_GET['kml'])) $kmlFile="kml_files/".urldecode($_GET['kml']);
if (isset($_GET['range'])) $range=$_GET['range']+0; // additional nodes to show (all other closer than this distance (in meters))
if (isset($_GET['mask'])) $maskFile="kml_files/".urldecode($_GET['mask']);
if (isset($_GET['ohref'])) $ohref=urldecode($_GET['ohref']); // right side of the image url (will compare only this long, prefix may be ommitted)
if (isset($_GET['corr-alt'])) $corrAlt=$_GET['corr-alt']+0;
if (isset($_GET['corr-lat'])) $corrLat=$_GET['corr-lat']+0;
if (isset($_GET['corr-lon'])) $corrLon=$_GET['corr-lon']+0;
if (isset($_GET['interpolate-range'])) $interpolateRange=true;
if (isset($_GET['view'])) $forceViewMode=true;
if (isset($_GET['proto'])) $protoFile="kml_files/".urldecode($_GET['proto']);
if (isset($_GET['relative-kml'])) $relative2kml=true;
if ((strpos ($kmlFile, '..' )!==false) || (strpos ($kmlFile, '.kml' )===false)) $kmlFile="";
if ((strpos ($protoFile,'..' )!==false) || (strpos ($protoFile, '.kml' )===false)) $protoFile="";
if ((strpos ($maskFile, '..' )!==false) || (strpos ($maskFile, '.kml' )===false)) $maskFile="";
// copy $protoFile to $kmlFile if $kml file does not exist and $protoFile is specified. In failure use $protoFile as $kmlFile in read only mode
if ($protoFile!="") {
if (!file_exists($kmlFile)) {
$okClone= ($protoFile!="") && file_exists($protoFile) && copy ($protoFile , $kmlFile);
if ($okClone) {
chmod($kmlFile, 0666);
} else {
$kmlFile=$protoFile;
$forceViewMode=true;
}
}
// if cloneProtoKML($prefix,$kmlFile,$protoFile)
}
/*
echo "<pre>\n";
echo "kmlFile=$kmlFile\n";
echo "maskFile=$maskFile\n";
echo "protoFile=$protoFile\n";
exit (0);
*/
// $writable=is_writable($kmlFile); // does not work on community
if (($kmlFile!="") && file_exists($kmlFile)) {
$perms = fileperms($kmlFile);
$writable=($perms & 2)!=0;
if ($forceViewMode) $writable=false;
$kmlValid=true;
} else {
generateKML(-1); // empty
exit (0);
}
// if (isset($_GET['v3d'])) {$generateVisibility3d=true;$applyVisibility3d=false;} // may be used separately
if (isset($_GET['map'])) switch ($_GET['map']) {
case "full": $fullMap= true;break;
case "interpolate": $interpolate=true; $allNodes=true; break;
case "all": $allNodes= true; break;
case "full-all": $fullMap= true; $allNodes=true; break;
} else {
}
if (!$writable) {
// $interpolate=false;
// $allNodes=false;
$generateVisibility3d=false;
// $applyVisibility3d=true;
$applyVisibility3d=!$allNodes;
$corrAlt=0;
$ohref="";
} else {
$generateVisibility3d=true;
$applyVisibility3d=false;
}
$prefix='http://'.$_SERVER['SERVER_NAME'].dirname($_SERVER['PHP_SELF']).'/';
if (dirname($kmlFile)!='.') $prefix.=dirname($kmlFile).'/';
parseKML($prefix,$kmlFile);
/*
echo "<pre>\n";
print_r($world);
echo "</pre>\n";
exit(0);
*/
if ($fullMap) orderWorldAsHrefs();
if ($maskFile !="") {
$world_original=$world;
$worldAttr_original=$worldAttr;
$world=array();
$worldAttr=array();
parseKML($prefix,$maskFile);
if ($fullMap) orderWorldAsHrefs();
for ($i=0;$i<count($world);$i++) {
$world_original[$i]=array_merge($world_original[$i],$world[$i]);
}
$worldAttr_original=array_merge($worldAttr_original,$worldAttr);
$world=$world_original;
$worldAttr=$worldAttr_original;
}
// endpoints always keypoints
$world[0]['visibility']="1";
$world[count($world)-1]['visibility']="1";
fixMissingCoordinates($interpolate);
fixSameCoordinates(); // TODO: improve interpolation later
if (!$allNodes) removeInvisible();
connectMap($fullMap); // when false - just previous/next
// TODO: - add other param,eters (i.e. resolution)
// Also - redirect instead of passthrough with header('Location: '.) - will it be faster?
$currentIndex=findHref($href,$longitude="",$latitude="");
if ($currentIndex<0) $currentIndex=0; // start with first if not specified/found
if ($ohref!="") $otherIndex=findHref($ohref);
if ((($corrAlt!=0) || ($corrLat!=0) || ($corrLon!=0))&& ($otherIndex>=0) && ($otherIndex!=$currentIndex)) {
correctAltitude( $currentIndex, $otherIndex,$corrAlt,$corrLat,$corrLon);
}
if ($interpolateRange && ($otherIndex>=0) && ($otherIndex!=$currentIndex)) {
interpolateRange($currentIndex, $otherIndex);
}
//$interpolateRange
generateKML($currentIndex,$range,$applyVisibility3d,$generateVisibility3d, $writable);
exit (0);
function interpolateRange($thisIndex, $otherIndex) {
global $world;
if ($otherIndex<$thisIndex) {
$tmp=$otherIndex;
$otherIndex=$thisIndex;
$thisIndex=$tmp;
}
$startTime=$world[$thisIndex]['timestamp'];
$endTime= $world[$otherIndex]['timestamp'];
$duration=$endTime-$startTime; // may be negative;
$deltaAltitude= $world[$otherIndex]['altitude'] -$world[$thisIndex]['altitude'];
$deltaLatitude= $world[$otherIndex]['latitude'] -$world[$thisIndex]['latitude'];
$deltaLongitude=$world[$otherIndex]['longitude']-$world[$thisIndex]['longitude'];
for ($i=$thisIndex+1; $i<$otherIndex;$i++) {
$thistTime=$world[$i]['timestamp'];
$world[$i]['altitude']= $world[$thisIndex]['altitude'] + $deltaAltitude*($thistTime-$startTime)/$duration;
$world[$i]['latitude']= $world[$thisIndex]['latitude'] + $deltaLatitude*($thistTime-$startTime)/$duration;
$world[$i]['longitude']=$world[$thisIndex]['longitude'] + $deltaLongitude*($thistTime-$startTime)/$duration;
}
}
function correctAltitude($thisIndex, $otherIndex, $deltaAlt,$deltaLat,$deltaLon) {
global $world;
$startTime=$world[$thisIndex]['timestamp'];
$endTime= $world[$otherIndex]['timestamp'];
$duration=$endTime-$startTime; // may be negative;
/*
echo "<pre>\n";
echo "thisIndex=$thisIndex\n";
echo "otherIndex=$otherIndex\n";
echo "deltaAlt=$deltaAlt\n";
echo "deltaLat=$deltaLat\n";
echo "deltaLon=$deltaLon\n";
echo "</pre>\n";
exit (0);
*/
if ($otherIndex>$thisIndex){
for ($i=$otherIndex;$i<count($world);$i++) {
$world[$i]['altitude']+=$deltaAlt;
$world[$i]['latitude']+=$deltaLat;
$world[$i]['longitude']+=$deltaLon;
}
for ($i=$thisIndex+1; $i<$otherIndex;$i++) {
$thistTime=$world[$i]['timestamp'];
$world[$i]['altitude']+= $deltaAlt*($thistTime-$startTime)/$duration;
$world[$i]['latitude']+= $deltaLat*($thistTime-$startTime)/$duration;
$world[$i]['longitude']+=$deltaLon*($thistTime-$startTime)/$duration;
}
} else if ($otherIndex<$thisIndex){
for ($i=0; $i<=$otherIndex;$i++) {
$world[$i]['altitude']+=$deltaAlt;
$world[$i]['latitude']+=$deltaLat;
$world[$i]['longitude']+=$deltaLon;
}
for ($i=$thisIndex+1; $i>$otherIndex;$i--) {
$thistTime=$world[$i]['timestamp'];
$world[$i]['altitude']+= $deltaAlt*($thistTime-$startTime)/$duration;
$world[$i]['latitude']+= $deltaLat*($thistTime-$startTime)/$duration;
$world[$i]['longitude']+=$deltaLon*($thistTime-$startTime)/$duration;
}
}
}
function findHref($href,$longitude="",$latitude="") {
global $world,$numNodes;
$currentIndex=-1;
if (($latitude!="") || ($longitude!="") || ($href!="")) foreach ($world as $index=>$node) {
if ( (($latitude=="") || ($node['latitude'] ==$latitude)) &&
(($longitude=="") || ($node['longitude']==$longitude)) &&
(($href=="") || ((strlen($node['href'])>=strlen($href)) && (substr($node['href'],-strlen($href))==$href) )))
$currentIndex=$index;
}
return $currentIndex;
}
function removeInvisible() {
global $world,$numNodes;
$world_original=$world;
$world=array();
for ($i=0;$i<count($world_original);$i++) if (!isset($world_original[$i]['visibility']) || ($world_original[$i]['visibility']!="0")) $world[count($world)]=$world_original[$i];
$numNodes=count($world);
}
function orderWorldAsHrefs() {
global $world;
$hrefs=array();
for ($i=0;$i<count($world);$i++) $hrefs[$i]=$world[$i]['href'];
array_multisort($hrefs,SORT_ASC, SORT_STRING,
$world);
}
function fixMissingCoordinates($interpolate, $useTimeStamps=true) { // in interpolate mode use "visibility" as bad coordinates (if specified and is "0")
global $world;
//make sure the world is in time acsending order (using string comparison of href)
$validCoord=array();
for ($i=0;$i<count($world);$i++)
$validCoord[$i]=isset($world[$i]['longitude']) &&
isset($world[$i]['latitude']) &&
isset($world[$i]['altitude']) &&
(!$interpolate || !isset($world[$i]['visibility']) || ($world[$i]['visibility']!="0"));
$i0=0;
// skip missing coord;
while (($i0<count($world)) && !$validCoord[$i0]) $i0++;
while ($i0<count($world)) {
// skip good coord;
while (($i0<count($world)) && $validCoord[$i0]) $i0++;
if ($i0<count($world)) {
// find next good
$i1=$i0;
$i0--;
while (($i1<count($world)) && !$validCoord[$i1]) $i1++;
// missing from $i0+1 to $i1-1;
// now using timestamps, not numbers
if ($i1<count($world)) {
if ($useTimeStamps) {
$startTime=$world[$i0]['timestamp'];
$endTime= $world[$i1]['timestamp'];
$duration=$endTime-$startTime;
for ($i=1;$i<($i1-$i0);$i++) {
$k=($world[$i+$i0]['timestamp']-$startTime)/$duration;
$world[$i+$i0]['longitude']=$world[$i0]['longitude']+($world[$i1]['longitude']-$world[$i0]['longitude'])*$k;
$world[$i+$i0]['latitude']= $world[$i0]['latitude']+ ($world[$i1]['latitude']-$world[$i0]['latitude'])*$k;
$world[$i+$i0]['altitude']= $world[$i0]['altitude']+ ($world[$i1]['altitude']-$world[$i0]['altitude'])*$k;
}
} else {
for ($i=1;$i<($i1-$i0);$i++) {
$world[$i+$i0]['longitude']=$world[$i0]['longitude']+($world[$i1]['longitude']-$world[$i0]['longitude'])*$i/($i1-$i0);
$world[$i+$i0]['latitude']= $world[$i0]['latitude']+ ($world[$i1]['latitude']-$world[$i0]['latitude'])*$i/($i1-$i0);
$world[$i+$i0]['altitude']= $world[$i0]['altitude']+ ($world[$i1]['altitude']-$world[$i0]['altitude'])*$i/($i1-$i0);
}
}
}
$i0=$i1;
}
}
// original values are strings, results - float
/*
echo "<pre>\n";
var_dump($world);
echo "</pre>\n";
exit(0);
*/
}
function fixSameCoordinates() {
global $world, $map, $numNodes;
//make sure the world is in time acsending order (using string comparison of href)
$hrefs=array();
for ($i=0;$i<count($world);$i++) $hrefs[$i]=$world[$i]['href'];
array_multisort($hrefs,SORT_ASC, SORT_STRING,
$world);
for ($i=0;$i<(count($world)-1);$i++) {
if (($world[$i]['longitude']==$world[$i+1]['longitude']) &&
($world[$i]['latitude']==$world[$i+1]['latitude']) &&
($world[$i]['altitude']==$world[$i+1]['altitude'])) {
$pair=array(array('longitude'=>$world[$i]['longitude'],
'latitude'=> $world[$i]['latitude'],
'altitude'=> $world[$i]['altitude']),
array('longitude'=>$world[$i+1]['longitude'],
'latitude'=> $world[$i+1]['latitude'],
'altitude'=> $world[$i+1]['altitude']));
// move first point
if ($i>0) {
$world[$i]['longitude']=(2*$pair[0]['longitude']+$world[$i-1]['longitude'])/3;
$world[$i]['latitude']= (2*$pair[0]['latitude']+ $world[$i-1]['latitude'])/3;
$world[$i]['altitude']= (2*$pair[0]['altitude']+ $world[$i-1]['altitude'])/3;
}
if ($i<(count($world)-2)) {
$world[$i+1]['longitude']=(2*$pair[1]['longitude']+$world[$i+2]['longitude'])/3;
$world[$i+1]['latitude']= (2*$pair[1]['latitude']+ $world[$i+2]['latitude'])/3;
$world[$i+1]['altitude']= (2*$pair[1]['altitude']+ $world[$i+2]['altitude'])/3;
}
}
}
// original values are strings, results - float
/*
echo "<pre>\n";
var_dump($world);
echo "</pre>\n";
exit(0);
*/
}
function checkVisibility($world, $this, $other) {
if (!isset ($world[$this]['v3d'])) return true; // visibility not specified -> visible
$thisIndex=$world[$this]['name']+0;
$otherIndex=$world[$other]['name']+0; // use name as index, otherwise some nodes may be filtered out already
foreach ( $world[$this]['v3d'] as $range) {
if ((!isset ($range['from']) || ($otherIndex>=($thisIndex+$range['from']))) && (!isset ($range['to']) || ($otherIndex<=($thisIndex+$range['to'])))) return 1;
}
return 0;
}
function generateKML($index,$distance=0,$filterInvisible3d=true, $generateV3d=false, $writable=true) {
global $world, $worldAttr, $map, $numNodes;
$kml=<<<HEADER
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.2">
<Document>
HEADER;
if ($index>=0) {
$kml.= sprintf("<open>%s</open>\n",($writable?1:0));
if (isset($worldAttr['cameraType']) || isset($worldAttr['aboveGround'])) {
$kml.= "<ExtendedData>\n";
if (isset($worldAttr['cameraType'])) $kml.= sprintf("<cameraType>%s</cameraType>\n",$worldAttr['cameraType']);
if (isset($worldAttr['aboveGround'])) $kml.= sprintf("<aboveGround>%s</aboveGround>\n",$worldAttr['aboveGround']);
$kml.= "</ExtendedData>\n";
}
$indices=array_merge(array(0=>$index),$map[$index]);
// apply "<open>" tag 0/1 here - needed invisible cameras will be arrows
if ($filterInvisible3d) for ($i=1;$i<count($indices);$i++) { // i=0 - not needed (same camera visibility)
$world[$indices[$i]]['open']=checkVisibility($world, $index, $indices[$i]);
//$kml.= '<!--'.$index.':'.$i.' - '.checkVisibility($world, $index, $indices[$i]).' -->';
//$kml.= '<!--'.$indices[$i].' ->> '.$world[$indices[$i]]['open'].' -->';
}
// iterate all pairs, fast way would be to compare lat/long separately
if ($distance>0) {
for ($i=0;$i<$numNodes;$i++) if ((array_search($i,$indices)===false) && (distance($world[$i]['latitude'],$world[$i]['longitude'],$world[$index]['latitude'],$world[$index]['longitude']) < $distance) &&
(!$filterInvisible3d || checkVisibility($world, $index, $i))) {
$indices[count($indices)]=$i;
if ($filterInvisible3d) $world[$i]['open']='1'; // apply to all, they are open
}
}
foreach ($indices as $i) {
if (!isset($world[$i]['heading'])) $world[$i]['heading']=0;
if (!isset($world[$i]['tilt'])) $world[$i]['tilt']=90;
if (!isset($world[$i]['roll'])) $world[$i]['roll']=0;
if (!$writable) $world[$i]['visibility']="1"; // no ghosts in readonly mode?
$kml.= "<PhotoOverlay>\n";
if (isset($world[$i]['name'])) $kml.=sprintf(" <name>%s</name>\n",$world[$i]['name']);
if (isset($world[$i]['description'])) $kml.=sprintf(" <description>%s</description>\n",$world[$i]['description']);
if (isset($world[$i]['visibility'])) $kml.= sprintf(" <visibility>%s</visibility>\n",$world[$i]['visibility']);
if (isset($world[$i]['open'])) $kml.= sprintf(" <open>%s</open>\n",$world[$i]['open']);
$kml.= " <Camera>\n";
$kml.=sprintf(" <longitude>%s</longitude>\n",$world[$i]['longitude']);
$kml.=sprintf(" <latitude>%s</latitude>\n",$world[$i]['latitude']);
$kml.=sprintf(" <altitude>%s</altitude>\n",$world[$i]['altitude']);
$kml.=sprintf(" <heading>%s</heading>\n",$world[$i]['heading']);
$kml.=sprintf(" <tilt>%s</tilt>\n",$world[$i]['tilt']);
$kml.=sprintf(" <roll>%s</roll>\n",$world[$i]['roll']);
$kml.= " </Camera>\n";
if (isset ($world[$i]['when'])) {
$kml.=" <TimeStamp>\n";
$kml.=sprintf(" <when>%s</when>\n",$world[$i]['when']);
$kml.=" </TimeStamp>\n";
}
$kml.= " <Icon>\n";
$kml.=sprintf(" <href>%s</href>\n",$world[$i]['href']);
$kml.= " </Icon>\n";
if ($generateV3d && isset($world[$i]['v3d'])) {
$kml.= " <ExtendedData>\n";
$kml.= " <Visibility3d>\n";
foreach ($world[$i]['v3d'] as $range) {
$kml.= " <v3Range>\n";
if (isset($range['from'])) $kml.=sprintf(" <from>%s</from>\n",$range['from']);
if (isset($range['to'])) $kml.=sprintf(" <to>%s</to>\n",$range['to']);
$kml.= " </v3Range>\n";
}
$kml.= " </Visibility3d>\n";
$kml.= " </ExtendedData>\n";
}
$kml.= "</PhotoOverlay>\n";
}
}
$kml.=<<<TRAILER
</Document>
</kml>
TRAILER;
header("Content-Type: text/xml\n");
header("Content-Length: ".strlen($kml)."\n");
header("Pragma: no-cache\n");
echo ($kml);
}
function connectMap($full) {
global $world, $map, $distances,$numNodes;
$numNodes=count($world);
if (!$full) {
$map=array();
$map[0]=array(1);
$map[$numNodes-1]=array($numNodes-2);
for ($i=1;$i<$numNodes-1;$i++) $map[$i]=array($i-1,$i+1);
return;
}
$distances=array();
for ($i=1;$i<$numNodes;$i++) {
$distances[$i]=array();
for ($j=0;$j<$i;$j++) $distances[$i][$j]= distance($world[$i]['latitude'],$world[$i]['longitude'],$world[$j]['latitude'],$world[$j]['longitude']);
}
$map0=array();
for ($i=0;$i<$numNodes;$i++) $map0[$i]=-1;
$map0[0]=0;
$built=false;
while (!$built) {
$built=true;
for ($i=1;$i< $numNodes;$i++) if ($map0[$i]<0) {
$built=false;
break;
}
if ($built) break;
$min=360; // more than maximal distance
$iMin=-1;
for ($i=0;$i<$numNodes;$i++) if ($map0[$i]>=0) {
for ($j=1;$j<$numNodes;$j++) if ($map0[$j]<0) {
$dist=($j>$i)?$distances[$j][$i]:$distances[$i][$j];
if ($dist<$min) {
$min=$dist;
$iMin=$i;
$jMin=$j;
}
}
}
if ($iMin<0) {
echo "failed to find a pair";
exit (1);
}
$map0[$jMin]=$iMin;
}
$map=array();
for ($i=0;$i<$numNodes;$i++) $map[$i]=array();
for ($i=1;$i<$numNodes;$i++) {
$j= $map0[$i];
$map[$i][count($map[$i])]=$j;
$map[$j][count($map[$j])]=$i;
}
}
function distance ($lat1,$long1,$lat2,$long2) {
$earthRadius=6378100; //meters
$dlat= $lat2- $lat1;
$dlong=$long2-$long1;
$lat=($lat1+$lat2)/2;
$dlong*= cos(deg2rad($lat));
return pi()*$earthRadius/180* sqrt($dlat*$dlat+$dlong*$dlong);
}
<?
/*
*! -----------------------------------------------------------------------------**
*! FILE NAME : modify_kml.php
*! REVISION : 1.0
*! DESCRIPTION: save changes to a file.
*! Copyright (C) 2011 Elphel, Inc.
*!
*! -----------------------------------------------------------------------------**
*! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*!
*! It means that the program's users have the four essential freedoms:
*!
*! * The freedom to run the program, for any purpose (freedom 0).
*! * The freedom to study how the program works, and change it to make it do what you wish (freedom 1).
*! Access to the source code is a precondition for this.
*! * The freedom to redistribute copies so you can help your neighbor (freedom 2).
*! * The freedom to distribute copies of your modified versions to others (freedom 3).
*!
*! By doing this you can give the whole community a chance to benefit from your changes.
*! Access to the source code is a precondition for this.
*! -----------------------------------------------------------------------------**
*/
require_once("call_filter.php");
$target_filename = "kml_files/".$_GET['kml'];
$target_xml = simplexml_load_file($target_filename);
$changes_xml = simplexml_load_file('php://input');
$new_PhotoOverlay = $changes_xml->Document->PhotoOverlay;
$old_PhotoOverlay = $target_xml->Document->PhotoOverlay;
foreach ($new_PhotoOverlay as $new_node) {
foreach ($old_PhotoOverlay as $old_node) {
$old_str = "{$old_node->Icon->href}";
$new_str = "{$new_node->Icon->href}";
//if ("{$new_node->Icon->href}"=="{$old_node->Icon->href}") {
if (strstr($new_str,$old_str)!=false) {
$old_node->name = $new_node->name;
$old_node->description = $new_node->description;
$old_node->visibility = $new_node->visibility;
if (!isset($old_node->Camera)) $old_node->Camera= $new_node->Camera;
$old_node->Camera->latitude = $new_node->Camera->latitude;
$old_node->Camera->longitude = $new_node->Camera->longitude;
$old_node->Camera->altitude = $new_node->Camera->altitude;
$old_node->Camera->heading = $new_node->Camera->heading;
$old_node->Camera->tilt = $new_node->Camera->tilt;
$old_node->Camera->roll = $new_node->Camera->roll;
if (!isset($old_node->ExtendedData) && isset($old_node->ExtendedData)) $old_node->ExtendedData= $new_node->ExtendedData;
if (isset($new_node->ExtendedData->Visibility3d->v3Range)) {
$old_node->ExtendedData->Visibility3d = $new_node->ExtendedData->Visibility3d;
/*
for ($nr=0; $nr<$new_node->ExtendedData->Visibility3d->v3Range->count();$nr++) {
$old_node->ExtendedData->Visibility3d->v3Range[$nr]= $new_node->ExtendedData->Visibility3d->v3Range[$nr];
if (isset($new_node->ExtendedData->Visibility3d->v3Range[$nr]->from)) $old_node->ExtendedData->Visibility3d->v3Range[$nr]->from=$new_node->ExtendedData->Visibility3d->v3Range[$nr]->from;
if (isset($new_node->ExtendedData->Visibility3d->v3Range[$nr]->to))$old_node->ExtendedData->Visibility3d->v3Range[$nr]->to= $new_node->ExtendedData->Visibility3d->v3Range[$nr]->to;
}
*/
$nr=0;
foreach ($new_node->ExtendedData->Visibility3d->children() as $child) {
$old_node->ExtendedData->Visibility3d->v3Range[$nr]= $child;
if (isset($child->from)) $old_node->ExtendedData->Visibility3d->v3Range[$nr]->from=$child->from;
if (isset($child->to))$old_node->ExtendedData->Visibility3d->v3Range[$nr]->to= $child->to;
$nr++;
}
}
break;
}
}
}
file_put_contents($target_filename, $target_xml->asXML());
?>
<?php
/*
*! -----------------------------------------------------------------------------**
*! FILE NAME : prepare_images_for_wpe.php
*! REVISION : 1.0
*! DESCRIPTION: cuts a panorama into 8 squares with 1px overlapping
*! Copyright (C) 2011 Elphel, Inc.
*!
*! -----------------------------------------------------------------------------**
*! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*!
*! It means that the program's users have the four essential freedoms:
*!
*! * The freedom to run the program, for any purpose (freedom 0).
*! * The freedom to study how the program works, and change it to make it do what you wish (freedom 1).
*! Access to the source code is a precondition for this.
*! * The freedom to redistribute copies so you can help your neighbor (freedom 2).
*! * The freedom to distribute copies of your modified versions to others (freedom 3).
*!
*! By doing this you can give the whole community a chance to benefit from your changes.
*! Access to the source code is a precondition for this.
*! -----------------------------------------------------------------------------**
*/
$w = 14272;
$h = 4654;
if (!isset($_GET['path'])) {
printf("No such folder");
exit(-1);
}
// manage a slash in the path string
$path=cut_path_ending_slash($_GET['path']);
if (!is_dir("$path/result")) {
mkdir("$path/result");
exec("chmod 777 $path/result");
}
foreach (scandir($path) as $value) {
process_images($path,$value);
}
function process_images($path,$file) {
global $w,$h;
//resize
$ext=get_file_extension($file);
if ($ext=="tif") {
$basename = basename($file,".tif");
echo ($w-1)." \n";
//cut the left column:
exec("convert $path/$file -crop ".($w-4)."x".$h."-".($w-5)." $path/result/$file");
exec("convert $path/$file $path/result/$file +append $path/result/$file");
exec("convert $path/result/$file -background Black -extent ".($w-3)."x".($w/2-1)." $path/result/$file");
for ($j=0;$j<2;$j++) {
for ($i=0;$i<4;$i++) {
$tmp_name = "$path/result/{$basename}_".($i+$j*4+1)."_8.$ext";
exec("convert $path/result/$file -crop ".( $w-3)."x".( $w/2-1)."-".((3-$i)*$w/4-(3-$i))."-".((1-$j)*$w/4-(1-$j))." $tmp_name");
exec("convert $tmp_name -crop ".(($i+1)*$w/4-$i)."x".(($j+1)*$w/4-$j)."+".( $i*$w/4-$i)."+".( $j*$w/4-$j)." $tmp_name");
exec("convert $tmp_name $path/result/{$basename}_".($i+$j*4+1)."_8.jpeg");
exec("rm $path/result/{$basename}_".($i+$j*4+1)."_8.$ext");
}
}
exec("rm $path/result/$file");
}
}
function cut_path_ending_slash($path) {
if (substr($path,-1,1)=="/") $path=substr($path,0,-1);
return $path;
}
function get_file_extension($filename) {
return pathinfo($filename, PATHINFO_EXTENSION);
}
function get_file_basename($filename) {
return substr($filename,0,strpos($filename,"."));
}
?>
\ No newline at end of file
<?php
$world=array();
$worldAttr=array();
$state=array('currentNode'=>-1,
'urlPrefix'=>'',
'currentValue'=>'',
'imgOn'=>false,
'ExtendedData'=>false,
'Visibility3d'=>false,
'v3Range'=>false);
function startElement($parser, $name, $attrs)
{
global $world,$state;
switch ($name) {
case 'PhotoOverlay':
$state['currentNode']=count($world);
$world[$state['currentNode']]=array();
break;
case 'Icon':
if (!$state['ExtendedData']) $state['imgOn']=true;
break;
case 'ExtendedData':
$state['ExtendedData']=true;
break;
case 'Visibility3d':
$state['Visibility3d']=true;
$world[$state['currentNode']]['v3d']=array();
break;
case 'v3Range':
$state['v3Range']=true;
$world[$state['currentNode']]['v3d'][count($world[$state['currentNode']]['v3d'])]=array();
break;
}
}
function endElement($parser, $name)
{
global $world,$worldAttr,$state;
$currentNode=$state['currentNode'];
$currentValue=$state['currentValue'];
if (!$state['ExtendedData']) {
switch ($name) {
case 'longitude':
$world[$currentNode]['longitude']=$currentValue;
break;
case 'latitude':
$world[$currentNode]['latitude']=$currentValue;
break;
case 'altitude':
$world[$currentNode]['altitude']=$currentValue;
break;
case 'heading':
$world[$currentNode]['heading']=$currentValue;
break;
case 'tilt':
$world[$currentNode]['tilt']=$currentValue;
break;
case 'roll':
$world[$currentNode]['roll']=$currentValue;
break;
case 'name':
$world[$currentNode]['name']=$currentValue;
break;
case 'description':
$world[$currentNode]['description']=$currentValue;
break;
case 'visibility':
$world[$currentNode]['visibility']=$currentValue;
break;
case 'Icon':
$state['imgOn']=false;
break;
case 'href':
if ($state['imgOn']) {
if (substr($currentValue,0,strlen("http://"))=="http://") $world[$currentNode]['href']=$currentValue;
else $world[$currentNode]['href']=$state['urlPrefix'].$currentValue;
}
break;
case 'when': // adds just a single element when, disregarding were in the current PhotoOverlay it is
$world[$currentNode]['when']=$currentValue;
$aDate=date_parse($currentValue);
$world[$currentNode]['timestamp']= mktime ($aDate['hour'],$aDate['minute'],$aDate['second'],$aDate['month'],$aDate['day'],$aDate['year'] )+$aDate['fraction'];
break;
}
} else { // parsing ExtendedData
switch ($name) {
// global world attributes (not per-node) - assuming all images made with the same camera - TODO - add overwrite for individual parameters?
case 'cameraType':
$worldAttr['cameraType']=$currentValue;
break;
case 'aboveGround':
$worldAttr['aboveGround']=$currentValue;
break;
// per-node parameters
case 'ExtendedData':
$state['ExtendedData']=false;
break;
case 'Visibility3d':
$state['Visibility3d']=false;
break;
case 'v3Range':
$state['v3Range']= false;
break;
}
if ($state['v3Range']) switch ($name) {
case 'to':
$world[$state['currentNode']]['v3d'][count($world[$state['currentNode']]['v3d'])-1]['to']=$currentValue;
break;
case 'from':
$world[$state['currentNode']]['v3d'][count($world[$state['currentNode']]['v3d'])-1]['from']=$currentValue;
break;
}
}
}
function characterData($parser, $data)
{
global $state;
$state['currentValue']=$data;
}
// $base - directory, where there is the .kml file, root directory for image files
function parseKML($prefix,$name) {
global $world,$state;
$state['urlPrefix']=$prefix;
$xml_parser = xml_parser_create();
// use case-folding so we are sure to find the tag in $map_array
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, false);
xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_set_character_data_handler($xml_parser, "characterData");
$data=file_get_contents($name);
if (!xml_parse($xml_parser, $data)) {
die(sprintf("XML error: %s at line %d",
xml_error_string(xml_get_error_code($xml_parser)),
xml_get_current_line_number($xml_parser)));
}
xml_parser_free($xml_parser);
return $world;
}
?>
\ No newline at end of file
<?php
/********************************************************************************
*! FILE NAME : pano_db_functions.php
*! DESCRIPTION: functions for the db
*! VERSION: 1.0
*! AUTHOR: Sebastian Pichelhofer, Oleg Dzhimiev <oleg@elphel.com>
*! Copyright (C) 2011 Elphel, Inc
*! -----------------------------------------------------------------------------**
*! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! The four essential freedoms with GNU GPL software:
*! * the freedom to run the program for any purpose
*! * the freedom to study how the program works and change it to make it do what you wish
*! * the freedom to redistribute copies so you can help your neighbor
*! * the freedom to distribute copies of your modified versions to others
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------**
*! $Log: pano_db_functions.php,v $
*!
*/
function ConnectMySQL () {
$sql_host = 'localhost';
$sql_db = '';
$sql_user = '';
$sql_pass = '';
$con = mysql_connect("$sql_host","$sql_user","$sql_pass");
if ($con) {
//skip
$db = mysql_select_db("$sql_db",$con);
if (!$db){
//die ("Cannot select the $sql_db database.<br />Please check your details in the database connection file and try again");
return false;
}else{
return true;
}
}else{
//die ("Cannot connect to MySql.");
return false;
}
}
// Save a new route to the DB supplying all database field as array
/*
xml array fields are:
$nodes[$i]->name
$nodes[$i]->description
*/
function AddRoute ($name,$description) {
$return['name'] = $name;
// check if the route already exists
$sqlq = "SELECT * FROM routes WHERE Name = '".$name."' AND Description = '".$description."'";
$result = mysql_query($sqlq) or die("Database error <br />" . mysql_error()); // why die()?
$entries = mysql_num_rows($result);
if (!$entries) {
$sqlq = "INSERT INTO routes (Name, Description) VALUES ('".$name."', '".($description)."')";
$result = mysql_query($sqlq) or die("Database error <br />" . mysql_error());
$return['id'] = mysql_insert_id();
} else {
$return['error'] = "Entry already exists";
}
return $return;
}
// Update a Route - overwrite field with values provided as parameter array
// ID field is mandatory
function UpdateRoute($id,$name=null,$description=null) {
$return['ID'] = $id;
// check if the Route exists
$sqlq = "SELECT * FROM routes WHERE ID = '".$id."'";
$result = mysql_query($sqlq) or die("Database error <br />" . mysql_error());
$exists = mysql_fetch_array($result, MYSQL_BOTH);
if ($exists['ID'] != "") { // does it exist?
$values = "";
if (isset($name)) {
$values .= "`Name`='".$name."', ";
}
if (isset($description)) {
$values .= "Description='".$description."', ";
}
$values = substr($values, 0, strlen($values)-2); // get rid of last ','
$sqlq = "UPDATE routes SET ".$values." WHERE ID = '".($id)."'";
$result = mysql_query($sqlq) or die("Database error <br />" . mysql_error());
$return['success'] = "congrats";
} else {
$return['error'] = "Route with ID: ".($id)." not found";
}
return $return;
}
// Returns all Nodes associated with a Route
function GetNodesByRoute ($id) {
// Check if Route with $RouteID exists before continuing
$sqlq = "SELECT * FROM routes WHERE ID = '".$id."'";
$result = mysql_query($sqlq) or die("Database error <br />" . mysql_error());
$exists = mysql_fetch_array($result, MYSQL_BOTH);
if ($exists['ID'] == "") {
$return['error'] = "Route with ID=".$id." not found";
return $return;
}
$index = 0;
$sqlq = "SELECT * FROM nodes LEFT JOIN routes_nodes ON nodes.ID = routes_nodes.NodeID WHERE routes_nodes.RouteID = '".$id."' ORDER BY `routes_nodes`.`Order` ASC";
$result = mysql_query($sqlq) or die("Database error <br />" . mysql_error());
while($rows = mysql_fetch_array($result, MYSQL_BOTH)) {
$return[$index]['ID'] = $rows['ID'];
$return[$index]['Order'] = $rows['Order'];
$return[$index]['Name'] = $rows['Name'];
$return[$index]['Description'] = $rows['Description'];
$return[$index]['OriginalDataLongitude'] = $rows['OriginalDataLongitude'];
$return[$index]['OriginalDataLatitude'] = $rows['OriginalDataLatitude'];
$return[$index]['OriginalDataAltitude'] = $rows['OriginalDataAltitude'];
$return[$index]['OriginalDataHeading'] = $rows['OriginalDataHeading'];
$return[$index]['OriginalDataTilt'] = $rows['OriginalDataTilt'];
$return[$index]['OriginalDataRoll'] = $rows['OriginalDataRoll'];
$return[$index]['Longitude'] = $rows['Longitude'];
$return[$index]['Latitude'] = $rows['Latitude'];
$return[$index]['Timestamp'] = $rows['Timestamp'];
$return[$index]['TimeStampMilliseconds'] = $rows['TimeStampMilliseconds'];
$return[$index]['Altitude'] = $rows['Altitude'];
$return[$index]['Heading'] = $rows['Heading'];
$return[$index]['Tilt'] = $rows['Tilt'];
$return[$index]['Roll'] = $rows['Roll'];
$return[$index]['PanoramaURL'] = $rows['PanoramaURL'];
$return[$index]['Visibility3D'] = $rows['Visibility3D'];
$index++;
}
if ($index==0) {
$return['error'] = "Route with the ID=".$id." is empty ";
}
return $return;
}
function DeleteRoute($id) {
// check if a Route with the provided $RouteID exists
$return['id'] = $id;
$sqlq = "SELECT * FROM routes WHERE ID = '".$id."'";
$results = mysql_query($sqlq) or die("Database error <br />" . mysql_error());
$routeexists = mysql_num_rows($results);
$nodes_count = 0;
if ($routeexists) {
// also delete all nodes that the route contains
$nodes = GetNodesByRoute($id);
if (!isset($nodes['error'])) {
foreach ($nodes as $node) {
// delete nodes associated with this route
$sqlq = "DELETE FROM nodes WHERE ID = '".$node['ID']."'";
$results = mysql_query($sqlq) or die("Database error <br />" . mysql_error());
$nodes_count++;
}
// delete route
$sqlq = "DELETE FROM routes WHERE ID = '".$id."'";
$results = mysql_query($sqlq) or die("Database error <br />" . mysql_error());
// delete route-node relationship
// do this at last or otherwise we don't know which nodes belong to which route anymore
$sqlq = "DELETE FROM routes_nodes WHERE RouteID = '".$id."'";
$results = mysql_query($sqlq) or die("Database error <br />" . mysql_error());
}else{
//$return[$i]['fail'] = "check1";
// delete route
$sqlq = "DELETE FROM routes WHERE ID = '".$id."'";
$results = mysql_query($sqlq) or die("Database error <br />" . mysql_error());
// delete route-node relationship
// do this at last or otherwise we don't know which nodes belong to which route anymore
$sqlq = "DELETE FROM routes_nodes WHERE RouteID = '".$id."'";
$results = mysql_query($sqlq) or die("Database error <br />" . mysql_error());
}
$return['success'] = "congrats";
$return['entries'] = $nodes_count;
} else {
$return['error'] = "Route with ID=".$id." does not exist";
}
return $return;
}
// Returns all database fields of a specific Route ID as array
function GetRouteData ($id) {
$sqlq = "SELECT * FROM routes WHERE ID = '".$id."'";
$result = mysql_query($sqlq) or die("Database error <br />" . mysql_error());
$exists = mysql_fetch_array($result, MYSQL_BOTH);
if ($exists['ID'] != "") {
$return['ID'] = $exists['ID'];
$return['Name'] = $exists['Name'];
$return['Description'] = $exists['Description'];
} else {
$return['error'] = "ID ".$id." not found";
}
return $return;
}
// Returns all Routes with Nodes associated and the location of their first Node
function GetRoutes () {
//$sqlq = "SELECT * FROM nodes LEFT JOIN routes_nodes ON nodes.ID = routes_nodes.NodeID LEFT JOIN routes ON routes.ID = routes_nodes.RouteID WHERE routes_nodes.Order = '1'";
$sqlq = "SELECT * FROM routes";
$result = mysql_query($sqlq) or die("Database error <br />" . mysql_error());
$index = 0;
while($rows = mysql_fetch_array($result, MYSQL_BOTH)) {
$return[$index]['ID'] = $rows['ID'];
$return[$index]['Name'] = $rows['Name'];
$return[$index]['Description'] = $rows['Description'];
//$return[$index]['Latitude'] = $rows['Latitude'];
//$return[$index]['Longitude'] = $rows['Longitude'];
$return[$index]['Nodes'] = GetNodeCount($rows['ID']);
$index++;
}
if ($index==0) $return[0]['error']="No routes found";
return CreateXMLStringFromArray($return);
}
// Returns all Routes with Nodes associated and the location of their first Node
function GetRoutesAndKMLs ($skip_db) {
//$sqlq = "SELECT * FROM nodes LEFT JOIN routes_nodes ON nodes.ID = routes_nodes.NodeID LEFT JOIN routes ON routes.ID = routes_nodes.RouteID WHERE routes_nodes.Order = '1'";
$index = 0;
if ($skip_db){
$sqlq = "SELECT * FROM routes";
$result = mysql_query($sqlq) or die("Database error <br />" . mysql_error());
while($rows = mysql_fetch_array($result, MYSQL_BOTH)) {
$return[$index]['ID'] = $rows['ID'];
$return[$index]['Name'] = $rows['Name'];
$return[$index]['Description'] = $rows['Description'];
//$return[$index]['Latitude'] = $rows['Latitude'];
//$return[$index]['Longitude'] = $rows['Longitude'];
$return[$index]['Nodes'] = GetNodeCount($rows['ID']);
$index++;
}
}
$result_files = search_kmls();
for ($i=0;$i<count($result_files);$i++){
$return[$index]['ID'] = $result_files[$i]['Name'];
$return[$index]['Editable'] = $result_files[$i]['Editable'];
$return[$index]['Nodes'] = $result_files[$i]['Nodes'];
$index++;
}
if ($index==0) $return[0]['error']="No routes found";
return CreateXMLStringFromArray($return);
}
function search_kmls(){
$index = 0;
$tmp_list = scandir("kml_files");
foreach($tmp_list as $some_file) {
$info = pathinfo("kml_files/".$some_file);
if ($info['extension']=="kml") {
$result[$index]['Name'] = $some_file;
if (is__writable("kml_files/".$some_file)) $result[$index]['Editable'] = "Yes";
else $result[$index]['Editable'] = "No";
$result[$index]['Nodes'] = get_number_of_nodes_in_kml_file("kml_files/".$some_file);
$index++;
}
}
return $result;
}
function get_number_of_nodes_in_kml_file($file){
$tmp_xml = simplexml_load_file($file);
$nodes = $tmp_xml->children()->children();
return count($nodes);
}
// Returns the number of Nodes currently stored in the DB
// If you supply a RouteID you can get the number of nodes associated with a specific route.
function GetNodeCount($id) {
if ($id=="") {
$sqlq = "SELECT * FROM nodes";
$result = mysql_query($sqlq) or die("Database error <br />" . mysql_error());
$return = mysql_num_rows($result);
}else{
$sqlq = "SELECT * FROM routes_nodes WHERE RouteID = '".$id."'";
$result = mysql_query($sqlq) or die("Database error <br />" . mysql_error());
$return = mysql_num_rows($result);
}
return $return;
}
// Save a new node to the DB supplying all database field as array:
/*
Array fields are:
$data['Name'],
$data['Description'],
$data['OriginalDataLongitude'],
$data['OriginalDataLatitude'],
$data['OriginalDataAltitude'],
$data['OriginalDataHeading'],
$data['OriginalDataTilt'],
$data['OriginalDataRoll'],
$data['Longitude'],
$data['Latitude'],
$data['Timestamp'],
$data['TimeStampMilliseconds'],
$data['Altitude'],
$data['Heading'],
$data['Tilt'],
$data['Roll'],
$data['PanoramaURL'],
$data['Visibility3D']
*/
function AddNode ($ArrayData) {
/*
$sqlq = "SELECT * FROM nodes WHERE OriginalDataLongitude = '".$ArrayData['OriginalDataLongitude']."' AND OriginalDataLatitude = ".$ArrayData['OriginalDataLatitude']." AND OriginalDataLatitude = ".$ArrayData['OriginalDataAltitude'];
*/
//override... panoramaurl is unique for now
$sqlq = "SELECT * FROM nodes WHERE PanoramaURL = '".$ArrayData['PanoramaURL']."'";
$results = mysql_query($sqlq) or die("Database error <br />" . mysql_error());
$exists = mysql_num_rows($results);
if (!$exists) {
/*
$sqlq = "INSERT INTO nodes (Name, Description, OriginalDataLongitude, OriginalDataLatitude, OriginalDataAltitude,
OriginalDataHeading, OriginalDataTilt, OriginalDataRoll, Longitude, Latitude, Timestamp,
TimeStampMilliseconds, Altitude, Heading, Tilt, Roll, PanoramaURL, Visibility3D)
VALUES
('".$ArrayData['Name']."', '".$ArrayData['Description']."', '".$ArrayData['OriginalDataLongitude']."',
'".$ArrayData['OriginalDataLatitude']."', '".$ArrayData['OriginalDataAltitude']."', '".$ArrayData['OriginalDataHeading']."',
'".$ArrayData['OriginalDataTilt']."', '".$ArrayData['OriginalDataRoll']."', '".$ArrayData['Longitude']."', '".$ArrayData['Latitude']."',
'".$ArrayData['Timestamp']."', '".$ArrayData['TimeStampMilliseconds']."', '".$ArrayData['Altitude']."', '".$ArrayData['Heading']."',
'".$ArrayData['Tilt']."', '".$ArrayData['Roll']."', '".$ArrayData['PanoramaURL']."', '".$ArrayData['Visibility3D']."')";
*/
$string_keys = "";
$string_values = "";
foreach ($ArrayData as $key=>$val) {
$string_keys .= $key.", ";
$string_values .= "'$val', ";
}
$string_keys = substr($string_keys,0,-2);
$string_values = substr($string_values,0,-2);
$sqlq = "INSERT INTO nodes ($string_keys) VALUES ($string_values)";
$result = mysql_query($sqlq) or die("Database error <br />" . mysql_error());
$return['id'] = mysql_insert_id();
} else {
$return['error'] = "Entry with exactly the same coordinates already exists";
//get id
$exists = mysql_fetch_array($results, MYSQL_BOTH);
$return['id'] = $exists['ID'];
}
return $return;
}
// Returns all database fields of a specific Node with ID as array
function GetNodeData ($ID) {
$sqlq = "SELECT * FROM nodes WHERE ID = '$ID'";
$result = mysql_query($sqlq) or die("Database error <br />" . mysql_error());
$exists = mysql_fetch_array($result, MYSQL_BOTH);
if ($exists['ID'] != "") { // does it exist?
$return['ID'] = $exists['ID'];
$return['Name'] = $exists['Name'];
$return['Description'] = $exists['Description'];
$return['OriginalDataLongitude'] = $exists['OriginalDataLongitude'];
$return['OriginalDataLatitude'] = $exists['OriginalDataLatitude'];
$return['OriginalDataAltitude'] = $exists['OriginalDataAltitude'];
$return['OriginalDataHeading'] = $exists['OriginalDataHeading'];
$return['OriginalDataTilt'] = $exists['OriginalDataTilt'];
$return['OriginalDataRoll'] = $exists['OriginalDataRoll'];
$return['Longitude'] = $exists['Longitude'];
$return['Latitude'] = $exists['Latitude'];
$return['Timestamp'] = $exists['Timestamp'];
$return['TimeStampMilliseconds'] = $exists['TimeStampMilliseconds'];
$return['Altitude'] = $exists['Altitude'];
$return['Heading'] = $exists['Heading'];
$return['Tilt'] = $exists['Tilt'];
$return['Roll'] = $exists['Roll'];
$return['PanoramaURL'] = $exists['PanoramaURL'];
$return['Visibility3D'] = $exists['Visibility3D'];
} else {
$return['error'] = "ID not found";
}
return $return;
}
// Update a Node - overwrite field with values provided as parameter array, fields like "OriginalDataLongitude" cannot be overwritten
// ID field is mandatory
function UpdateNode($Parameters) {
// check if the node exists
$return['id'] = $Parameters['ID'];
$sqlq = "SELECT * FROM nodes WHERE ID = '".$Parameters['ID']."'";
$result = mysql_query($sqlq) or die("Database error <br />" . mysql_error());
$exists = mysql_fetch_array($result, MYSQL_BOTH);
if ($exists['ID'] != "") { // does it exist?
$values = "";
foreach ($Parameters as $key=>$val) {
$values .= "$key = '$val', ";
}
$values = substr($values,0,-2);
$sqlq = "UPDATE nodes SET ".$values." WHERE ID = '".$Parameters['ID']."'";
$result = mysql_query($sqlq) or die("Database error <br />" . mysql_error());
$return['success'] = "congrats";
} else {
$return['error'] = "Node with ID: ".$Parameters['ID']." not found";
}
return $return;
}
// Add a node to a specific route supplying both IDs
function AddNodeToRoute ($NodeID, $RouteID) {
// check if the entry we are trying to add does not exist already
$sqlq = "SELECT * FROM routes_nodes WHERE RouteID = '$RouteID' AND NodeID = '$NodeID'";
$results = mysql_query($sqlq) or die("Database error <br />" . mysql_error());
$exists = mysql_num_rows($results);
if (!$exists) {
// check if a node with the provided $NodeID exists
$sqlq = "SELECT * FROM nodes WHERE ID = '$NodeID'";
$results = mysql_query($sqlq) or die("Database error <br />" . mysql_error());
$nodeexists = mysql_num_rows($results);
if ($nodeexists) {
// check if a route with the provided $RouteID exists
$sqlq = "SELECT * FROM routes WHERE ID = '$RouteID'";
$results = mysql_query($sqlq) or die("Database error <br />" . mysql_error());
$routeexists = mysql_num_rows($results);
if ($routeexists) {
$Order_Value = GetNodeCount($RouteID) + 1; // order is just incremented with every new entry for now
// all checks pass, now add the actual entry
$sqlq = "INSERT INTO routes_nodes (`RouteID`, `NodeID`, `Order`) VALUES ('".$RouteID."', '".$NodeID."', '".$Order_Value."')";
$result = mysql_query($sqlq) or die("Database error <br />" . mysql_error());
$return['success'] = "congrats";
} else {
$return['error'] = "Route with supplied ID does not exist";
}
} else {
$return['error'] = "Node with supplied ID does not exist: ".$NodeID;
}
} else {
$return['error'] = "Entry already exists";
}
return $return;
}
function DeleteNode($NodeID) {
// check if a Node with the provided $NodeID exists
$sqlq = "SELECT * FROM nodes WHERE ID = '$NodeID'";
$results = mysql_query($sqlq) or die("Database error <br />" . mysql_error());
$nodeexists = mysql_num_rows($results);
if ($nodeexists) {
$sqlq = "DELETE FROM nodes WHERE ID = '$NodeID'";
$results = mysql_query($sqlq) or die("Database error <br />" . mysql_error());
$sqlq = "DELETE FROM routes_nodes WHERE NodeID = '$NodeID'";
$results = mysql_query($sqlq) or die("Database error <br />" . mysql_error());
$return['success'] = "congrats";
} else {
$return['error'] = "Entry with NodeID: ".$NodeID." does not exist";
}
return $return;
}
function RemoveNodeFromRoute($NodeID, $RouteID) {
// since this is intended for clean up don't check if the Node or Route we aim to delete still exists
// just check if the entry we want to delete is not already gone
$sqlq = "SELECT * FROM routes_nodes WHERE RouteID = '$RouteID' AND NodeID = '$NodeID'";
$results = mysql_query($sqlq) or die("Database error <br />" . mysql_error());
$entryexists = mysql_num_rows($results);
if ($entryexists) {
$sqlq = "DELETE FROM routes_nodes WHERE RouteID = '$RouteID' AND NodeID = '$NodeID'";
$results = mysql_query($sqlq) or die("Database error <br />" . mysql_error());
$return['success'] = "done";
} else {
$return['error'] = "Entry with NodeID: ".$NodeID." and RouteID: ".$RouteID." does not exist";
}
return $return;
}
function GetNodeIDbyImageFileName($RouteID, $Filename) {
$sqlq = "SELECT * FROM nodes LEFT JOIN routes_nodes ON nodes.ID = routes_nodes.NodeID WHERE routes_nodes.RouteID = '$RouteID' AND PanoramaURL LIKE '%$Filename%'";
$result = mysql_query($sqlq) or die("Database error <br />" . mysql_error());
$exists = mysql_fetch_array($result, MYSQL_BOTH);
if ($exists['ID'] != "") { // does it exist?
$return['id'] = $exists['ID'];
} else {
$return['error'] = "no results";
}
return $return;
}
// Find an array of nodes that are in the area of the supplied coordinates (LatMin, LatMax, LongMin, LongMax).
// To prevent a huge number of results there is the limit parameter with a default value of 100.
// the results are not returned in a particular order
function GetNodesAt ($LatMin, $LatMax, $LongMin, $LongMax, $Limit = 100) {
// prevent zero results of min and max are swapped
if ($LatMin >= $LatMax) {
$helper = $LatMin;
$LatMin = $LatMax-0.0000000001;
$LatMax = $helper+0.0000000001;
}
if ($LongMin >= $LongMax) {
$helper = $LongMin;
$LongMin = $LongMax-0.0000000001;
$LongMax = $helper+0.0000000001;
}
// SQL BETWEEN statement can't deal with negative values so we do it this way
$sqlq = "SELECT * FROM nodes WHERE Latitude >= '$LatMin' AND Latitude <= '$LatMax' AND Longitude >= '$LongMin' AND Longitude <= '$LongMax'";
$result = mysql_query($sqlq) or die("Database error <br />" . mysql_error());
$i = 0;
while ($exists = mysql_fetch_array($result, MYSQL_BOTH)) {
if ($i > $Limit)
break;
if ($exists['ID'] != "") { // does it exist?
$return[$i]['ID'] = $exists['ID'];
$return[$i]['Name'] = $exists['Name'];
$return[$i]['Description'] = $exists['Description'];
$return[$i]['OriginalDataLongitude'] = $exists['OriginalDataLongitude'];
$return[$i]['OriginalDataLatitude'] = $exists['OriginalDataLatitude'];
$return[$i]['OriginalDataAltitude'] = $exists['OriginalDataAltitude'];
$return[$i]['OriginalDataHeading'] = $exists['OriginalDataHeading'];
$return[$i]['OriginalDataTilt'] = $exists['OriginalDataTilt'];
$return[$i]['OriginalDataRoll'] = $exists['OriginalDataRoll'];
$return[$i]['Longitude'] = $exists['Longitude'];
$return[$i]['Latitude'] = $exists['Latitude'];
$return[$i]['Timestamp'] = $exists['Timestamp'];
$return[$i]['TimeStampMilliseconds'] = $exists['TimeStampMilliseconds'];
$return[$i]['Altitude'] = $exists['Altitude'];
$return[$i]['Heading'] = $exists['Heading'];
$return[$i]['Tilt'] = $exists['Tilt'];
$return[$i]['Roll'] = $exists['Roll'];
$return[$i]['PanoramaURL'] = $exists['PanoramaURL'];
$return[$i]['Visibility3D'] = $exists['Visibility3D'];
$i++;
}
}
return $return;
}
function GetNodesDistance ($Node1ID, $Node2ID) {
// we assume that the 2 nodes have no big altitude difference and calculate the distance based on their longitude and latitude on the earth sphere surface
$continue = true;
$node1 = GetNodeData($Node1ID);
if (isset($node1['error'])) {
$return['error'] = "Node 1: ".$node1['error'];
$continue = false;
}
$node2 = GetNodeData($Node2ID);
if (isset($node2['error'])) {
$return['error'] = "Node 2: ".$node2['error'];
$continue = false;
}
if ($continue) {
$earthRadius = 6378100; //meters
$delta_Latitude = $node2['Latitude'] - $node1['Latitude'];
$delta_Longitude = $node2['Longitude']- $node1['Longitude'];
$lat = ($node2['Latitude'] + $node1['Latitude']) / 2;
$dlong*= cos(deg2rad($lat));
$return['distance'] = pi() * $earthRadius / 180 * sqrt($delta_Latitude * $delta_Latitude + $delta_Longitude * $delta_Longitude);
} else {
//return $return;
}
return $return;
}
// Returns 2 Long/Lat pairs defining the rectangular bounds of this Route
function GetRouteBounds ($RouteID) {
// Check if Route with $RouteID exists before continuing
$sqlq = "SELECT * FROM routes WHERE ID = '$RouteID'";
$result = mysql_query($sqlq) or die("Database error <br />" . mysql_error());
$exists = mysql_fetch_array($result, MYSQL_BOTH);
if ($exists['ID'] == "") {
$return['error'] = "Route with ID: ".$RouteID." not found";
return $return;
}
$MinLong = 180;
$MaxLong = -180;
$MinLat = 90;
$MaxLat = -90;
// Load all Nodes from this Route
$Nodes = GetNodesByRoute($RouteID);
if (isset($Nodes['error'])) {
$return['error'] = $Nodes['error'];
}else{
// Find Min/Max
for ($i = 0; $i < count($Nodes);$i++) {
if ($Nodes[$i]['Latitude'] > $MaxLat) {
$MaxLat = $Nodes[$i]['Latitude'];
}
if ($Nodes[$i]['Latitude'] < $MinLat) {
$MinLat = $Nodes[$i]['Latitude'];
}
if ($Nodes[$i]['Longitude'] > $MaxLong) {
$MaxLong = $Nodes[$i]['Longitude'];
}
if ($Nodes[$i]['Longitude'] < $MinLong) {
$MinLong = $Nodes[$i]['Longitude'];
}
}
$return['MinLatitude'] = $MinLat;
$return['MaxLatitude'] = $MaxLat;
$return['MinLongitude'] = $MinLong;
$return['MaxLongitude'] = $MaxLong;
$return['CenterLatitude'] = $MinLat + ($MaxLat - $MinLat) / 2;
$return['CenterLongitude'] = $MinLong + ($MaxLong - $MinLong) / 2;
}
return $return;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Works just like AddNode but can import a high number of nodes with a single function - read from a KML file or KML String (if file is not found), if you supply a RouteID all new Nodes will automatically be added to an existing route.
function ImportKML ($KMLfile, $RouteID, $overwrite=false) {
$entries = 0;
if ($overwrite=="false") $overwrite = false;
$overwrite = true;
if (file_exists("kml_files/".$KMLfile)) {
$xml = simplexml_load_file("kml_files/".$KMLfile);
/*
else {
$xml = simplexml_load_string(html_entity_decode($KMLfile));
}
*/
foreach($xml->children()->children() as $child) {
// Loop through every panorama entry
//<PhotoOverlay id="12"> <- extract ID from this tag
if (isset($child->attributes()->id)) {
$data['ID'] = $child->attributes()->id;
$return['attention'] = $data['ID'];
}
/*
<Camera>
<longitude>-110.69838765920252</longitude>
<latitude>38.56224631822149</latitude>
<altitude>1429.72</altitude>
<heading>272.677574682831</heading>
<tilt>85.71949990886216</tilt>
<roll>10.35173368362165</roll>
</Camera>
<ExtendedData>
<OriginalData>
<longitude>-110.698398</longitude>
<latitude>38.562215</latitude>
<altitude>1430.6</altitude>
<heading>0</heading>
</OriginalData>
</ExtendedData>
*/
$data['Longitude'] = (string)$child->Camera->longitude;
if (isset($child->ExtendedData->OriginalData->longitude))
$data['OriginalDataLongitude'] = (string)$child->ExtendedData->OriginalData->longitude;
else
$data['OriginalDataLongitude'] = $data['Longitude'];
$data['Latitude'] = (string)$child->Camera->latitude;
if (isset($child->ExtendedData->OriginalData->latitude))
$data['OriginalDataLatitude'] = (string)$child->ExtendedData->OriginalData->latitude;
else
$data['OriginalDataLatitude'] = $data['Latitude'];
$data['Altitude'] = (string)$child->Camera->altitude;
if (isset($child->ExtendedData->OriginalData->altitude))
$data['OriginalDataAltitude'] = (string)$child->ExtendedData->OriginalData->altitude;
else
$data['OriginalDataAltitude'] = $data['Altitude'];
$data['Heading'] =(string)$child->Camera->heading;
if (isset($child->ExtendedData->OriginalData->heading))
$data['OriginalDataHeading'] = (string)$child->ExtendedData->OriginalData->heading;
else
$data['OriginalDataHeading'] = $data['Heading'];
$data['Tilt'] = (string)$child->Camera->tilt;
if (isset($child->ExtendedData->OriginalData->tilt))
$data['OriginalDataTilt'] = (string)$child->ExtendedData->OriginalData->tilt;
else
$data['OriginalDataTilt'] = $data['Tilt'];
$data['Roll'] = (string)$child->Camera->roll;
if (isset($child->ExtendedData->OriginalData->roll))
$data['OriginalDataRoll'] = (string)$child->ExtendedData->OriginalData->roll;
else
$data['OriginalDataRoll'] = $data['Roll'];
/*
<TimeStamp>
<when>2011-06-18T20:09:52.901982Z</when>
</TimeStamp>
*/
$temp = (string)$child->TimeStamp->when;
$data['Timestamp'] = substr($temp, 0, strpos($temp, "."));
$data['TimeStampMilliseconds'] = substr($temp, strpos($temp, ".") + 1, strlen($temp) - 1);
/*
<Icon>
<href>http://community.elphel.com/files/eyesis/webgl-pano/3/panos_gv/result_1303513568_466930-000001.jpeg</href>
</Icon>
*/
$data['PanoramaURL'] = (string)$child->Icon->href;
/*
<description>undefined</description>
<name>1</name>
*/
$data['Name'] = (string)$child->name;
if ($child->description == "undefined") {
$data['Description'] = "";
} else {
$data['Description'] = (string)$child->description;
}
/*
<Visibility3d>
<v3Range>
<to>6</to>
</v3Range>
<v3Range>
<from>21</from><to>21</to>
</v3Range>
<v3Range>
<from>24</from><to>25</to>
</v3Range>
<v3Range>
<from>27</from><to>41</to>
</v3Range>
</Visibility3d>
Lets transform this into a single string with "-" as "from to" and "|" as divider
-> "-6|21-21|24-25|27-41|"
*/
$data['Visibility3D'] = "";
if (isset($child->ExtendedData->Visibility3d)) {
foreach($child->ExtendedData->Visibility3d->v3Range as $v3Range) {
if(isset($v3Range->from)) {
$data['Visibility3D'] .= $v3Range->from."-".$v3Range->to."|";
} else {
$data['Visibility3D'] .= "-".$v3Range->to."|";
}
}
}
$NodeID = AddNode($data);
if (isset($NodeID['error'])) {
if ($overwrite) UpdateNode($data);
}
if (isset($RouteID)) {
$return[$entries] = AddNodeToRoute ($NodeID['id'], $RouteID);
if (isset($return[$entries]['error'])) {
$return[$entries]['failure'] = "condolences";
}else{
$return[$entries]['success'] = "congrats";
}
}
//print_r ($data);
// if ($overwrite) {
// UpdateNode($data);
// $return['AddNodeToRoute'] = AddNodeToRoute ($NodeID['id'], $RouteID);
// $return[$entries]['success'] = "congrats";
// } else {
// $NodeID = AddNode($data);
// if (isset($RouteID)) {
// if (!isset($NodeID['error'])) {
// $return['AddNodeToRoute'] = AddNodeToRoute ($NodeID['id'], $RouteID);
// $return[$entries]['success'] = "congrats";
// }else{
// $return[$entries]['error'] = "Already exists";
// }
// }
// }
$entries++;
}
$return[0]['Entries'] = $entries;
}else{
$return[0]['error'] = "No such file";
}
return $return;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function CreateKMLEntry($NodeData) {
// TODO: Visibility3d
$TimeStamp = $NodeData['Timestamp'].".".$NodeData['TimeStampMilliseconds']."Z";
$TimeStamp = str_replace(" ", "T", $TimeStamp);
$KMLOutput = "";
//$KMLOutput.= "<open>0</open>\n";
$KMLOutput .= "<PhotoOverlay id=\"".$NodeData['ID']."\">\n";
$KMLOutput .= "<visibility>1</visibility>
<name>".$NodeData['Name']."</name>
<shape>rectangle</shape>
<TimeStamp>
<when>".$TimeStamp."</when>
</TimeStamp>
<Camera>
<longitude>".$NodeData['Longitude']."</longitude>
<latitude>".$NodeData['Latitude']."</latitude>
<altitude>".$NodeData['Altitude']."</altitude>
<heading>".$NodeData['Heading']."</heading>
<tilt>".$NodeData['Tilt']."</tilt>
<roll>".$NodeData['Roll']."</roll>
</Camera>
<Icon>
<href>".$NodeData['PanoramaURL']."</href>
</Icon>
<ExtendedData>
<OriginalData>
<longitude>".$NodeData['OriginalDataLongitude']."</longitude>
<latitude>".$NodeData['OriginalDataLatitude']."</latitude>
<altitude>".$NodeData['OriginalDataAltitude']."</altitude>
<heading>".$NodeData['OriginalDataHeading']."</heading>
<tilt>".$NodeData['OriginalDataTilt']."</tilt>
<roll>".$NodeData['OriginalDataRoll']."</roll>
</OriginalData>
<Visibility3d>1</Visibility3d>
</ExtendedData>\n";
if ((!isset($NodeData['Description']))||($NodeData['Description']==""))
$KMLOutput .= "<description>no description</description>\n";
else
$KMLOutput .= "<description>".$NodeData['Description']."</description>\n";
$KMLOutput .= "<visibility>1</visibility>\n";
$KMLOutput.= "</PhotoOverlay>\n";
return $KMLOutput;
}
function PrintKML($kml) {
$content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
$content .= "<kml xmlns=\"http://earth.google.com/kml/2.2\">\n";
$content .= "<Document>\n";
$content .= "<open>0</open>\n";
$content .= $kml;
$content .= "</Document></kml>";
header("Content-Type: text/xml\n");
header("Content-Length: ".strlen($content)."\n");
header("Pragma: no-cache\n");
echo $content;
}
function CreateXMLStringFromArray($arr){
return AddXMLHeader(ArrayToXMLString($arr));
}
function ArrayToXMLString($a,$pre=""){
$str="";
foreach($a as $key=>$value){
if (is_array($value)) {
if (is_numeric($key)) $key = "li";
$str .= $pre."<$key>\n";
$str .= ArrayToXMLString($value,$pre." ");
$str .= $pre."</$key>\n";
}
else {
if (is_numeric($key)) $key = "li";
$str .= $pre."<$key>$value</$key>\n";
}
}
return $str;
}
function AddXMLHeader($str){
return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"."<response>\n<Document>\n".$str."</Document>\n</response>\n";
}
function is__writable($file){
if (file_exists($file)) {
$perms = fileperms($file);
return (($perms & 2)!=0);
}else{
return false;
}
}
?>
\ No newline at end of file
<?php
/********************************************************************************
*! FILE NAME : pano_db_inerface.php
*! DESCRIPTION: interface with the db
*! VERSION: 1.0
*! AUTHOR: Sebastian Pichelhofer, Oleg Dzhimiev <oleg@elphel.com>
*! Copyright (C) 2011 Elphel, Inc
*! -----------------------------------------------------------------------------**
*! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! The four essential freedoms with GNU GPL software:
*! * the freedom to run the program for any purpose
*! * the freedom to study how the program works and change it to make it do what you wish
*! * the freedom to redistribute copies so you can help your neighbor
*! * the freedom to distribute copies of your modified versions to others
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------**
*! $Log: pano_db_inerface.php,v $
*!
*/
//require_once("call_filter.php");
include("pano_db_functions.php");
if (isset($_GET['cmd'])) $cmd = $_GET['cmd'];
else die("Error Code: 13542");
$skip_db = ConnectMySQL();
$xml = @simplexml_load_file("php://input");
if ($xml) {
//pay attention to the command.
if (($cmd=="AddNode") || ($cmd=="UpdateNode")) {
$xml_nodes = $xml->PhotoOverlay;
}else{
$xml_nodes = $xml->node; //array of records
}
}
switch ($cmd) {
case "AddRoute" :
for($i=0;$i<count($xml_nodes);$i++) {
$response[$i] = AddRoute($xml_nodes[$i]->name,$xml_nodes[$i]->description);
}
send_response(CreateXMLStringFromArray($response));
break;
case "UpdateRoute":
for($i=0;$i<count($xml_nodes);$i++) {
//send_response(AddRoute($xml_nodes));
$response[$i] = UpdateRoute($xml_nodes[$i]->ID,$xml_nodes[$i]->name,$xml_nodes[$i]->description);
}
send_response(CreateXMLStringFromArray($response));
break;
case "GetNodesByRoute":
$Nodes = GetNodesByRoute($xml_nodes[0]->ID);
$kml = "";
if (isset($Nodes['error'])) {
send_response("<?xml version=\"1.0\"?>\n<result><node><error>".$Nodes['error']."</error></node></result>");
break;
}
foreach ($Nodes as $Node) {
if (!isset($Node['error'])) $kml .= CreateKMLEntry($Node);
else {
send_response(CreateXMLStringFromArray($Node['error']));
break;
}
}
if ($kml!="") PrintKML($kml);
else send_response("<?xml version=\"1.0\"?>\n<result><node><error>Some error, no apologies</error></node></result>");
// else if ($Args['return'] == "JSON") {
// $return = GetNodesByRoute($Args['parameters']['ID']);
// $output = $json->encode($return);
// print($output);
// }
break;
case "DeleteRoute" :
for($i=0;$i<count($xml_nodes);$i++) {
$response[$i] = DeleteRoute($xml_nodes[$i]->ID);
}
send_response(CreateXMLStringFromArray($response));
break;
case "GetRouteData":
//send_response(GetRouteData($xml_nodes));
for($i=0;$i<count($xml_nodes);$i++) {
$response[$i] = GetRouteData($xml_nodes[$i]->ID);
}
send_response(CreateXMLStringFromArray($response));
break;
case "GetRoutes" : send_response(GetRoutes()); break;
case "GetRoutesAndKMLs" : send_response(GetRoutesAndKMLs($skip_db)); break;
case "GetNodeCount":
if ($xml_nodes[0]->ID=="") {
$response[0]['id'] = "N/A";
$response[0]['total'] = GetNodeCount($xml_nodes[0]->ID);
}else{
for($i=0;$i<count($xml_nodes);$i++){
$response[$i]['id'] = $xml_nodes[$i]->ID;
$response[$i]['N'] = GetNodeCount($xml_nodes[$i]->ID);
}
}
send_response(CreateXMLStringFromArray($response));
break;
case "AddNode":
for($i=0;$i<count($xml_nodes);$i++) {
$response[$i] = AddNode(KMLRecord2Array($xml_nodes[$i]));
}
send_response(CreateXMLStringFromArray($response));
break;
case "GetNodeData":
for($i=0;$i<count($xml_nodes);$i++) {
$response[$i] = GetNodeData($xml_nodes[$i]->ID);
}
send_response(CreateXMLStringFromArray($response));
break;
case "UpdateNode":
for($i=0;$i<count($xml_nodes);$i++) {
$response[$i] = UpdateNode(KMLRecord2Array($xml_nodes[$i]));
}
send_response(CreateXMLStringFromArray($response));
break;
case "DeleteNode":
for($i=0;$i<count($xml_nodes);$i++) {
$response[$i] = DeleteNode($xml_nodes[$i]->ID);
}
send_response(CreateXMLStringFromArray($response));
break;
case "AddNodeToRoute":
for($i=0;$i<count($xml_nodes);$i++) {
$response[$i] = AddNodeToRoute($xml_nodes[$i]->NodeID,$xml_nodes[$i]->RouteID);
}
send_response(CreateXMLStringFromArray($response));
break;
case "RemoveNodeFromRoute":
for($i=0;$i<count($xml_nodes);$i++) {
$response[$i] = RemoveNodeFromRoute($xml_nodes[$i]->NodeID,$xml_nodes[$i]->RouteID);
}
send_response(CreateXMLStringFromArray($response));
break;
case "GetNodeIDbyImageFileName":
for($i=0;$i<count($xml_nodes);$i++) {
$response[$i] = GetNodeIDbyImageFileName($xml_nodes[$i]->RouteID,$xml_nodes[$i]->href);
}
send_response(CreateXMLStringFromArray($response));
break;
case "GetNodesAt":
//for($i=0;$i<count($xml_nodes);$i++) {
$response = GetNodesAt(
$xml_nodes[0]->latmin,
$xml_nodes[0]->latmax,
$xml_nodes[0]->lonmin,
$xml_nodes[0]->lonmax,
$xml_nodes[0]->limit
);
//}
send_response(CreateXMLStringFromArray($response));
break;
case "GetNodesDistance":
for($i=0;$i<count($xml_nodes);$i++) {
$response[$i] = GetNodesDistance(
$xml_nodes[$i]->ID1,
$xml_nodes[$i]->ID2
);
}
send_response(CreateXMLStringFromArray($response));
break;
case "GetRouteBounds":
for($i=0;$i<count($xml_nodes);$i++) {
$response[$i] = GetRouteBounds(
$xml_nodes[$i]->ID
);
}
send_response(CreateXMLStringFromArray($response));
break;
case "ImportKML":
//for($i=0;$i<count($xml_nodes);$i++) {
$response = ImportKML(
$xml_nodes[0]->path,
$xml_nodes[0]->RouteID,
$xml_nodes[0]->overwrite
);
//}
send_response(CreateXMLStringFromArray($response));
break;
}
function KMLRecord2Array($rec){
if (isset($rec->ID )) $data['ID'] = $rec->ID;
if (isset($rec->name)) $data['Name'] = $rec->name;
if (isset($rec->Description)) $data['Description']= $rec->Description;
if (isset($rec->ExtendedData->OriginalData->longitude)) $data['OriginalDataLongitude']= $rec->ExtendedData->OriginalData->longitude;
if (isset($rec->ExtendedData->OriginalData->latitude)) $data['OriginalDataLatitude'] = $rec->ExtendedData->OriginalData->latitude;
if (isset($rec->ExtendedData->OriginalData->altitude)) $data['OriginalDataAltitude'] = $rec->ExtendedData->OriginalData->altitude;
if (isset($rec->ExtendedData->OriginalData->heading)) $data['OriginalDataHeading'] = $rec->ExtendedData->OriginalData->heading;
if (isset($rec->ExtendedData->OriginalData->tilt)) $data['OriginalDataTilt'] = $rec->ExtendedData->OriginalData->tilt;
if (isset($rec->ExtendedData->OriginalData->roll)) $data['OriginalDataRoll'] = $rec->ExtendedData->OriginalData->roll;
if (isset($rec->Camera->longitude)) $data['Longitude'] = $rec->Camera->longitude;
if (isset($rec->Camera->latitude)) $data['Latitude'] = $rec->Camera->latitude;
if (isset($rec->Timestamp->when)) $data['Timestamp'] = $rec->Timestamp->when;
//$data['TimeStampMilliseconds'] = (isset($rec->))?$rec->:0;
if (isset($rec->Camera->altitude)) $data['Altitude'] = $rec->Camera->altitude;
if (isset($rec->Camera->heading)) $data['Heading'] = $rec->Camera->heading;
if (isset($rec->Camera->tilt)) $data['Tilt'] = $rec->Camera->tilt;
if (isset($rec->Camera->roll)) $data['Roll'] = $rec->Camera->roll;
if (isset($rec->Icon->href)) $data['PanoramaURL'] = $rec->Icon->href;
if (isset($rec->visibility)) $data['Visibility3D'] = $rec->visibility;
return $data;
}
function send_response($content) {
header("Content-Type: text/xml\n");
header("Content-Length: ".strlen($content)."\n");
header("Pragma: no-cache\n");
echo $content;
}
?>
\ No newline at end of file
<?php
/********************************************************************************
*! FILE NAME : permissions.php
*! DESCRIPTION: interface with the db
*! VERSION: 1.0
*! AUTHOR: Andrey Filippov
*! Copyright (C) 2011 Elphel, Inc
*! -----------------------------------------------------------------------------**
*! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! The four essential freedoms with GNU GPL software:
*! * the freedom to run the program for any purpose
*! * the freedom to study how the program works and change it to make it do what you wish
*! * the freedom to redistribute copies so you can help your neighbor
*! * the freedom to distribute copies of your modified versions to others
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------**
*! $Log: pano_db_inerface.php,v $
*!
*/
$fname=$_GET['name'];
$writable= is_writable($fname);
echo "file $fname is ".($writable?"writable":"not writable")."<br/>";
$perms = fileperms($fname);
echo "fileperms($fname)=".fileperms($fname)."<br/>";
if (($perms & 0xC000) == 0xC000) {
// Socket
$info = 's';
} elseif (($perms & 0xA000) == 0xA000) {
// Symbolic Link
$info = 'l';
} elseif (($perms & 0x8000) == 0x8000) {
// Regular
$info = '-';
} elseif (($perms & 0x6000) == 0x6000) {
// Block special
$info = 'b';
} elseif (($perms & 0x4000) == 0x4000) {
// Directory
$info = 'd';
} elseif (($perms & 0x2000) == 0x2000) {
// Character special
$info = 'c';
} elseif (($perms & 0x1000) == 0x1000) {
// FIFO pipe
$info = 'p';
} else {
// Unknown
$info = 'u';
}
// Owner
$info .= (($perms & 0x0100) ? 'r' : '-');
$info .= (($perms & 0x0080) ? 'w' : '-');
$info .= (($perms & 0x0040) ?
(($perms & 0x0800) ? 's' : 'x' ) :
(($perms & 0x0800) ? 'S' : '-'));
// Group
$info .= (($perms & 0x0020) ? 'r' : '-');
$info .= (($perms & 0x0010) ? 'w' : '-');
$info .= (($perms & 0x0008) ?
(($perms & 0x0400) ? 's' : 'x' ) :
(($perms & 0x0400) ? 'S' : '-'));
// World
$info .= (($perms & 0x0004) ? 'r' : '-');
$info .= (($perms & 0x0002) ? 'w' : '-');
$info .= (($perms & 0x0001) ?
(($perms & 0x0200) ? 't' : 'x' ) :
(($perms & 0x0200) ? 'T' : '-'));
echo $info;
?>
<?php
/********************************************************************************
*! FILE NAME : translate.php
*! DESCRIPTION: for possible multilingual use, not finished
*! VERSION: 1.0
*! AUTHOR: Oleg Dzhimiev <oleg@elphel.com>
*! Copyright (C) 2011 Elphel, Inc
*! -----------------------------------------------------------------------------**
*! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! The four essential freedoms with GNU GPL software:
*! * the freedom to run the program for any purpose
*! * the freedom to study how the program works and change it to make it do what you wish
*! * the freedom to redistribute copies so you can help your neighbor
*! * the freedom to distribute copies of your modified versions to others
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------**
*! $Log: translate.php,v $
*!
*/
require_once("call_filter.php");
$xml = new simpleXMLElement("<?xml version='1.0' encoding='UTF-8'?><Document></Document>");
$xml->Titles->title = "Panorama Viewer/Editor v1.1";
$xml->Titles->idViewAzimuth = "Turn 90 degrees right";
$xml->Titles->idViewElevation = "Reset to 0 degrees";
$xml->Titles->idShowPlan_tip = "Toggle a schematic plan of the map points locations";
$xml->Titles->idShowCams_tip = "Toggle the camera models shown above the panorama texture";
$xml->Titles->idClickCams_tip = "Click on the camera model or click on the footprint under the model to jump to the place of interest";
$xml->Titles->idShowLabels_tip = "Toggle distance showing labels";
$xml->Titles->idPermanentLink_div = "The permanent link to the current panorama with selected parameters";
$xml->Titles->idSettingsEdit_tip = "Depends on the chosed base KML file";
$xml->Titles->idSettingsProto_tip = "KML prototype file. Is used to create a new editable KML file. Choose an item from the list and fill in the KML file field";
$xml->Titles->idSettingsKml_tip = "KML file - Map points geo location data. To create a new editable KML file - choose the prototype file first, then fill this field: 'kml_files/new-kml.kml'. This field is used to create the Permanent Link.";
$xml->Titles->idSettingsMask_tip = "KML mask file. Allows to filter the map points by setting visibility. This field is used to create the Permanent Link.";
$xml->Titles->idSettingsStart_tip = "Starting panorama filename.";
$xml->Titles->idSettingsMap_tip = "Points connection algorithm. Works properly in the Edit Mode. This field is used to create the Permanent Link.";
$xml->Titles->idSettingsRange_tip = "Request all the points in the chosen range (in meters). This field is used to create the Permanent Link.";
$xml->Titles->idSettingsAsCamera_tip = "Camera model within the chosen range - an arrow outside the range (in meters). This field is used to create the Permanent Link.";
$xml->Titles->idSettingsNumTextures_tip = "Number of textures(panoramas) to buffer. This field is used to create the Permanent Link.";
$xml->Titles->idSettingsLabels_tip = "Show/hide distance labels. This field is used to create the Permanent Link.";
$xml->Titles->idSettingsClosestIn2D_tip = "Method for selecting a camera model. This field is used to create the Permanent Link.";
$xml->Titles->idSettingsKeepZoom_tip = "Keep zoom on window resize. This field is used to create the Permanent Link.";
$xml->Titles->idSettingsSeeThrough_tip = "Edit mode parameter. Visibility control of the current panorama and the previous. This field is used to create the Permanent Link.";
$xml->Titles->idSettingsTransitionTime_tip = "Transition time between panoramas. This field is used to create the Permanent Link.";
$xml->Titles->idSettingsFollow_tip = "Rotation with the camera (old heading - new heading). This field is used to create the Permanent Link.";
$xml->Titles->idSettingsMarkVisibility3d_tip = "Edit Mode Only. TBA. This field is used to create the Permanent Link.";
$xml->Titles->idSettingsPlan_tip = "Schematic plan of the map points.";
$xml->Titles->idSettingsDotSize_tip = "Radius of a dot on the plan.";
$xml->Titles->idSettingsThisColor_tip = "Color of the current location dot.";
$xml->Titles->idSettingsColor_tip = "Color of other dots.";
$xml->Titles->idSettingsSelectedColor_tip = "Color of the selected dot.";
$xml->Titles->idSettingsGhostColor_tip = "Color of the ghost dot.";
$xml->Titles->idSettingsInvisibleColor_tip = "Color of the invisible dot.";
$xml->Contents->idViewMode_Controls = "
<table style='font-size:14px'>
<tr>
<td><b>1.</b></td>
</tr>
<tr>
<td colspan='2'>The page can take parameters in the following format: <b>http://address/page.html?p1=v1&p2=v2&</b>... An example with all the parameters is the 'Permanent Link'</td>
</tr>
<tr>
<td><b>2.</b></td>
</tr>
<tr>
<td>
<b>drag</b>
</td>
<td>
'viewer turn'(azimuth,elevation angle)
</td>
</tr>
<tr>
<td>
<b>click</b>
</td>
<td>
on camera model/arrow/footprint - 'next'
</td>
</tr>
</table>
<table style='font-size:14px'>
<tr>
<td colspan='2'>
<b>Route navigation</b>:
</td>
</tr>
<tr>
<td>
Plan points, camera models, arrows and points on the maps are clickable.
</td>
</tr>
</table>
";
$xml->Contents->idEditMode_Controls = "
<span style='font-size:14px'>(editing technique is described at <a href='http://blog.elphel.com/2011/06/eyesis-outdoor-panorama-sets-and-the-viewereditor/'>blog.elphel.com</a>)(check the edit mode checkbox)</span>
<table style='font-size:14px'>
<tr><td>Horizon Alignment:</td><td></td></tr>
<tr><td><b>drag</b></td><td>'viewer turn'(azimuth,elevation)</td></tr>
<tr><td><b>shift+drag</b></td><td>'camera turn'(heading,tilt,roll) - correct camera orientation</td></tr>
<tr><td><b>ctrl+click</b></td><td> on the point of interest - 'fix a rotation axis' (helps to fix one of the horizontal plane vectors and by rotating about (with <b>shift-drag</b>) it adjust the horizon)</td></tr>
<tr><td>Location Correction:</td><td></td></tr>
<tr><td><b>click</b></td><td>on the camera model or a point on the plan to select the camera</td></tr>
<tr><td><b>drag</b></td><td> the red footprint to change the horizontal plane position of the selected camera</td></tr>
<tr><td><b>ctrl+alt+drag</b></td><td> the red footprint (or check the vertical move checkbox) to change the vertical camera position</td></tr>
<tr><td><br/>Other Edit Mode Tips:</td><td></td></tr>
<tr><td colspan='2'>
<b>A.</b> To create a new editable KML file choose the prototype KML file first, then fill the field <b>KML file</b> (example: 'kml_files/new-kml.kml' - editable files are stored in a subfolder <b>kml_files</b>).</br>
</br><b>B.</b> When other camera is selected, several buttons may appear:
<table style='font-size:14px'>
<tr>
<td>1.</td><td>when 'self' is selected the only option is 'clear visibility' - make it from -infinity to +infinity</td>
</tr>
<tr>
<td>2.</td><td>when currently visible camera is selected, and it is in the segment that includes your current camera (zero) and there are <b>no</b> segments farther, the only option is 'Hide far' - make selected and all farther cameras invisible</td>
</tr>
<tr>
<td>3.</td><td>when currently visible camera is selected, and it is in the segment that includes your current camera (zero) and there <b>are some</b> segments farther, 2 options will be available - 'Hide far' (same as in (2) and 'Trim far' - hide all cameras from the selected farther until the end of the segment</td>
</tr>
<tr>
<td>4.</td><td>when currently visible camera is selected, and it is <b>not</b> in the segment that includes your current camera (zero), there are 2 options 'Hide this' and 'Hide range'. The first just hidesa that single selected camera, the second hides all currently visible range that includes it (range may include infinity)</td>
</tr>
<tr>
<td>5.</td><td>when selected camera is invisible, there are 2 options - 'Show this' and 'Show range' - works similarly to 4), just opposite - shows selected camera or whole currently invisible range</td>
</tr>
</table>
<br/><b>C.</b> 'Interpolate'-button: distribute camera positions (lat, long, alt.) between the current and selected camera evenly (by time). When using that feature you need to have the current camera positions saved (using Save to KML). After the interpolation (if you are satisfied) you need to use 'Save to KML' again before moving to other spot.<br/>
<br/><b>D.</b> 'Move'('Insert Move'). To use that feature you need to make sure that all the map is requested (put sufficiently large &range=). This function is needed if you need to move many cameras together, insert vector between to camera spots. You can select and move some camera, and while it is still selected (do not press 'Save to KML'!) press 'Insert Move'. It will apply the movement vector that the selected camera was moved (difference between the red one and the 'ghost' one) to the selected camera and l the cameras that are farther (in the sense of the sequence number, time) than it. The cameras between current and selected (if there are any ) will be interpolated, the current cameras and all that are 'behind it' (sequence numbers/time in the opposite direction than the selected) remain unchanged. If you are satisfied with the results - 'Save to KML'.
</td>
</tr>
</table>
";
sendResponse($xml);
function sendResponse($xml){
header("Content-Type: text/xml\n");
header("Content-Length: ".strlen($xml->asXML())."\n");
header("Pragma: no-cache\n");
echo $xml->asXML();
}
?>
\ No newline at end of file
<html>
<head>
<!--
*! FILE NAME : webgl_panorama_editor.html
*! DESCRIPTION: WebGL panorama viewer/editor, used examples in "Learning WebGL"( http://learningwebgl.com/blog/?p=1253 )
*! VERSION: 1.3
*! AUTHOR:
*! Copyright (C) 2011 Elphel, Inc
*! -----------------------------------------------------------------------------**
*! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! The four essential freedoms with GNU GPL software:
*! * the freedom to run the program for any purpose
*! * the freedom to study how the program works and change it to make it do what you wish
*! * the freedom to redistribute copies so you can help your neighbor
*! * the freedom to distribute copies of your modified versions to others
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------**
*! $Log: pano_db_inerface.php,v $
*!
-->
<title>Panorama Viewer/Editor</title>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<link rel="some icon" href="files/images/fp_logo.png">
<script src="files/sylvester.js" type="text/javascript"></script>
<script src="files/glUtils.js" type="text/javascript" ></script>
<script src="files/get_kml.js" type="text/javascript" ></script>
<script src="files/sunpos.js" type="text/javascript" ></script>
<script src="files/jquery-1.6.4.min.js" type="text/javascript"></script>
<script src="files/jquery-ui-1.8.13.custom.min.js" type="text/javascript"></script>
<script src="files/modify_kml.js" type="text/javascript"></script>
<script src="files/webgl_subs.js" type="text/javascript"></script>
<script src="files/pano_mouse_events.js" type="text/javascript"></script>
<script src="files/plan_view.js" type="text/javascript"></script>
<script src="files/leaflet/leaflet.js"></script>
<link href="files/jquery-ui-1.8.13.custom.css" rel="stylesheet" type="text/css" />
<link href="files/panorama_viewer.css" rel="stylesheet" type="text/css" />
<script src="files/seethrough_slider.js"></script>
<script src="files/settings_dialog.js"></script>
<script src="files/translate.js"></script>
<script src="files/jquery_list.js"></script>
<link href="files/list.css" rel="stylesheet" type="text/css" />
<!--maps links start-->
<link type="text/css" href="files/maps.css" rel="stylesheet" />
<!-- an individual key must be generated for each website-->
<!--<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;sensor=false&amp;key=ABQIAAAAOfPl0ij7ARlHxPI3xKN-IhTbTdz52PKNAoxxGazVreAjPP4cQxScMIzHbNN8xU3Hdves_feAOgERIQ" type="text/javascript"></script>-->
<!--community-->
<!--<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;sensor=false&amp;key=ABQIAAAAOfPl0ij7ARlHxPI3xKN-IhQMu0AeT8-u_88N8Nw_CPBy6WRMERS0vfNxPxQnZDkvIrxd3Km94k8l6w" type="text/javascript"></script>-->
<!--irc-->
<!--<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;sensor=false&amp;key=ABQIAAAAOfPl0ij7ARlHxPI3xKN-IhQGja30efaXZL0SnkQH3NMeNhapzhQtlhhLN_73G6XnD-TFLQDoZIJyvg" type="text/javascript"></script>-->
<!--OSM begin-->
<!--<script type="text/javascript" src="http://www.openlayers.org/api/OpenLayers.js"></script>-->
<!--<script type="text/javascript" src="OpenStreetMap.js"></script>-->
<!--<script type="text/javascript">
var no_connection=true;
if (typeof(GBrowserIsCompatible)!="undefined") no_connection = false;
else no_connection = true;
</script>-->
<!--<script src="files/g_map_custom.js"></script>-->
<script src="files/os_map_custom.js"></script>
<!--OSM end-->
<!--maps links end-->
<script src="files/extras.js" type="text/javascript"></script>
<script src="files/dots.js"></script>
<link rel="stylesheet" type="text/css" href="files/leaflet/leaflet.css" />
<script id="shader-fs" type="x-shader/x-fragment">
#ifdef GL_ES
precision highp float;
#endif
varying vec2 vTextureCoord;
varying vec3 vLightWeighting;
uniform float uAlpha; // for blending
uniform sampler2D uSampler;
void main(void) {
vec4 textureColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));
gl_FragColor = vec4(textureColor.rgb * vLightWeighting, textureColor.a * uAlpha);
}
</script>
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
attribute vec3 aVertexNormal;
attribute vec2 aTextureCoord;
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
uniform mat4 uNMatrix;
uniform vec3 uAmbientColor;
uniform vec3 uLightingDirection;
uniform vec3 uDirectionalColor;
uniform bool uUseLighting;
varying vec2 vTextureCoord;
varying vec3 vLightWeighting;
void main(void) {
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
vTextureCoord = aTextureCoord;
if (!uUseLighting) {
vLightWeighting = vec3(1.0, 1.0, 1.0);
} else {
vec4 transformedNormal = uNMatrix * vec4(aVertexNormal, 1.0);
float directionalLightWeighting = max(dot(transformedNormal.xyz, uLightingDirection), 0.0);
vLightWeighting = uAmbientColor + uDirectionalColor * directionalLightWeighting;
}
}
</script>
<script type="text/javascript">
var no_connection = false;
var canvas;
var numSubTextures=8; //2; //8;
var documentRoot=window.location.href.substr(0,window.location.href.lastIndexOf('?'))
documentRoot=documentRoot.substr(0,documentRoot.lastIndexOf('/')+1);
var serverURL=documentRoot+"map_pano.php";
var showInfo=true;
// var arrows=[];
var arrows; // array of objects
/*{angle:0, // degrees, - direction?
down:0, // meters down
distance:0, // distance
type:"a"}; // "a" - arrow, "c" camera
*/
var floatingEyesisNum=-1;
var floatingEyesis={angle:0, // degrees, - direction?
down:0, // meters down
distance:0}; // distance
var floatingEyesisLLE={}; // latitude/longitude/elevation, calculated
var floatingEyesisVisible=false;
var floatingEyesisDragging=false; // true when clicked on floating Eyesis, moving it while mousedown
var floatingEyesisHorizontal=false; // true when clicked on floating Eyesis, moving it while mousedown
var floatingEyesisStart={}; // save initial values (for ortho)
var arrows_below=2.5;
var arrows_away= 15;
var worldRadius = 100; // meters to the sphere
var waitForPano=true;
// var arrowRadius= 25; //20; // distance (in viewport pixels) from the arrow center to select arrow in the viewport
var arrowRadius= 25; //20; // distance (in viewport pixels) from the arrow center to select arrow in the viewport
var maxPanoTilt=90; // maximal tilt of the panorama from vertical during HTR adjustment
var gl;
var lockedDirection=0;
var directionIsLocked=false;
var earthRadius=6378100; //meters
var latLongRounding=1000000; // rounding for showInformation
var altRounding=100; // rounding for showInformation
var orientRounding=100; // rounding for showInformation
var settings={
edit:false, // edit mode enabled
view:false,
numTextures:2, // number of simultaneous textures (loaded in background)
// kml:"map_goblins01.kml", // kml file ("database") to use
kml:"", // kml file ("database") to use
start:"", // image name of the start node
as_camera:95, // show as cameras if closer than that
range:10000, // request request all cameras in that radius
labels:false, // use div labels for hotspots
closestIn2d:false, // when cluttered, use closest hotspot in 2d (false - use nearest in distance the from viewer)
keepZoom:false, // when resizing window - keep zoom level (false - keep FOV)
planDotSize:5, // size of the square dot on the plan view
planThisColor:"#44cc44", // color of "this" camera on the plan view
planColor:"#4444cc", // color of the camera on the plan view
planColorSelected:"#ff4444",// color of the selected camera on the plan view
planColorGhost:"#ccaa44", // color of the "ghost"camera on the plan view
planColorInvisible:"#cccccc", // color of the camera on the plan view, having visibility=0 in KML
seethrough: 0.4, // show previous panorama (in edit mode)
transitionTime:5, // transition time between panoramas, seconds (0 - disable transiotion effect)
transitionSpeed:0, // if >0, uses transition speed in m/s
// transitionSteps:50, // transition transparency steps between panoramas
mask:"", // kml file to overwrite parameters in the main KML (mostly "visibility"?
proto:"",
map:"", // "" - suppose sequential (fast), "full" - rebuild map, "interpolate" (implies sequential) - use "visibility" as "valid coordinates", interpolate between
follow:false, // when jumping between cameras, look in the camera direction (or opposite - which is closer to the direction of jump)
Visibility3d: false, // request kml with full 3d visibility ranges (for editing), when false - reply will have tag <open> - 0 always arrow
fovy: 45,
markVisibility3d: false // highlight visible (in 3d) cameras, false - highlight keypoints
};
var Sun={azimuth:175.7,
elevation:66.7,
fraction:0.7, // fraction of directional light (1.0-fraction - diffused light)
directionalRGB:[1.0,1.0,1.0], // white
ambientRGB:[1.0,1.0,1.0], // white
unitVector:[0,0,1] // has to be calculated when this view, elevation or global view azimuth/elevation are changed
};
var panoTexturesSrc;
var panoTextures;
var panoImages;
var panoLoadedSubTextures;
var map = []; // nodes from kml and indises
var mapIndices; // from texture number to node number - number dependent on maximal number of textures
var fovYMin=10; // minimal horizontal angle of view
var fovYMax=120; // maximal horizontal angle of view
var fovY=45; // current horizontal angle of view
var fovK=1.1; // scaling of fovY per wheel delta
// var znear=0.1;
var znear=0.02;
// var znear=10;
var zfar= 100.0;
// var zfar= 2.0;
var currentTextureNumber=-1;
var previousTextureNumber=-1; // previous texture number for comparison in edit mode
var transitionSeeThrough=0; // see through old panorama during transition
var transitionStartLLE={}; // save map[0] latitude/longitude/elevation there
var transitionEndLLE={};
var transitionDeltaAngle;
var transitionEndTime;
var lastHeading; // should be undefined=0;
var currentTextureWidth=0;
var currentTextureHeight=0;
var maximalZoom=1.0; // relative to texture pixels
// var minimalZoom=.01; // relative to texture pixels (calculated from fovYMax) - local var
var currentZoom; // relative to texture pixels
var verticalEnabled=false;
/*
Orto mode is implemented using the model of a weight attached with a fixed length (orthoStep==10) string to a mouse pointer.
When the movement is just started (string was never tight), any direction is possible, as if ortho is off. As soon as the string
becomes tight first time, the rotation angles are restored to initial (at mousedown event) and the whole mouse movement (~=orthoStep)
is processed at once, deciding which of the two movements (vertiacal or horizontal) was farther - the other one is zeroed out.
During the movement, if the "string was tight" (distance between current mouse coordinates and savedX, savedY is greater than orthoStep,
the "weight" is moved towards pointer to the distance orthoStep from it, direction (vertical/horizontal) is re-calculated. If the string
is not tight (i.e. reverse of the movement direction), the selected direction is not changed (until the string will be tight again)
*/
var orthoStep=10; // use movement that far to select direction in ortho mode
var ortoDir=-1; // -1 - not aset, 0 - horizontal, 1 - vertical
var savedX, savedY, savedH, savedT, savedR, savedA, SavedE; // saved X, Y, Heading , Tilt,, roll (Azimuth, Elevation) at saved X, Y
var editEnabled=false; // TODO: use url parameters to turn editEnabled on/off - done
var showCams=true;
var clickCams=true; // click/label footprints
var showPlan;
function showInformation() {
if (showInfo) {
// var latLongRounding=1000000;
// var altRounding=100;
// var orientRounding=100;
var correctedHeading=map[0].heading-map[0].cameraHeading;
if (correctedHeading<360) correctedHeading+=360;
if (correctedHeading>360) correctedHeading-=360;
document.getElementById("idLongitude").value=Math.round(latLongRounding*map[0].longitude)/latLongRounding;
document.getElementById("idLatitude").value=Math.round(latLongRounding*map[0].latitude)/latLongRounding;
document.getElementById("idAltitude").value=Math.round(altRounding*map[0].altitude)/altRounding;
document.getElementById("idHeading").value=Math.round(orientRounding*correctedHeading)/orientRounding;
document.getElementById("idTilt").value=Math.round(orientRounding*(map[0].tilt-90))/orientRounding;
document.getElementById("idRoll").value=Math.round(orientRounding*map[0].roll)/orientRounding;
document.getElementById("idViewAzimuth").innerHTML=Math.round(orientRounding*azimuth)/orientRounding;
document.getElementById("idViewElevation").innerHTML=Math.round(-orientRounding*elevation)/orientRounding;
document.getElementById("idNodeName").innerHTML=(typeof(map[0].name!='undefined'))?map[0].name:"";
document.getElementById("idNodeDescription").value=(typeof(map[0].description!='undefined'))?map[0].description:"";
document.getElementById("idKeyPoint").checked=map[0].visibility;
}
}
function inputHTR() {
map[0].heading=parseInt(document.getElementById("idHeading").value)+map[0].cameraHeading;
if (map[0].heading<360) map[0].heading+=360;
if (map[0].heading>360) map[0].heading-=360;
map[0].tilt=parseInt(document.getElementById("idTilt").value)+90;
map[0].roll=parseInt(document.getElementById("idRoll").value);
recalcHTR();
drawScene(); //drawArrowsAndCams();
}
function unlockAxis(){
directionIsLocked=false;
document.getElementById("idLockedAxis").style.display="none";
}
function lockAxis(direction){
lockedDirection=direction;
directionIsLocked=true;
document.getElementById("idLockedAxisDirection").innerHTML=lockedDirection;
document.getElementById("idLockedAxis").style.display="";
}
function display_error(message){
var top = window.innerHeight;
var left = window.innerWidth;
$('#error_no_webgl').html(message);
top = (top/2)-$('#error_no_webgl').height()/2;
left = (left/2)-$('#error_no_webgl').width()/2;
$('#error_no_webgl').css({top: top+'px',left: left+'px'});
$('#error_no_webgl').show();
clearInterval(loading_intvl);
$("#status").hide();
}
function kmlGot(panos,writable) {
//applySettings();
if ((panos.length==0) || (typeof(panos[0].latitude)=="undefined")) {
//display_error("KML file is undefined, is corrupted or does not exist. Please provide the kml path in the url as '...html?kml=filename.kml&'");
display_error("The route is undefined or does not exist. Please provide the correct route name in the url as '...html?kml=route-name&'");
$('#idSettingsDialog').hide();
$("#idInfo_toggle").click();
document.getElementById("idPermanentLink_div").style.display="none";
return;
}
if ((panos.length<1)||(typeof(panos[0]))) {}
if (settings.start=="") settings.start = panos[0].href.substr(panos[0].href.lastIndexOf('/')+1);
if (((settings.transitionTime>0) || (settings.transitionSpeed>0)) && (currentTextureNumber>=0)) {
transitionStartLLE.latitude=map[0].latitude;
transitionStartLLE.longitude=map[0].longitude;
transitionStartLLE.altitude=map[0].altitude+0.2; // not to start from the camera itself
}
map=panos;
calcArrows();
if ((settings.transitionTime>0) || (settings.transitionSpeed>0)) {
transitionEndLLE.latitude=map[0].latitude;
transitionEndLLE.longitude=map[0].longitude;
transitionEndLLE.altitude=map[0].altitude;
}
writable = writable && !settings.view;
setWritableMode(writable);
if (settings.edit) calcVisibility3d();
showInformation();
if (!no_connection) {
//osm_remove_points();
osm_place_points();
osm_set_current_position(map[0]);
}
// try to reuse textures
for (var i=0;i<mapIndices.length;i++) mapIndices[i]=-1;
//document.title="panoTexturesSrc.length="+panoTexturesSrc.length;
for (var i=0;i<map.length;i++) {
map[i].textureNumber=-1;
for (var j=0; j<panoTexturesSrc.length; j++) if (map[i].href==panoTexturesSrc[j]) {
map[i].textureNumber=j; // new node has texture already cached
mapIndices[j]=i; // existent texture used around the new node
break;
}
}
for (var i=0;i<map.length;i++) { // will start from the most important
if (map[i].textureNumber<0) {
// First - try to (re)use those that are not needed and not equal to the current
for (var j=0;j<panoTexturesSrc.length; j++) if ((j!=currentTextureNumber) && (mapIndices[j]<0)) {
map[i].textureNumber=j;
mapIndices[j]=i;
break;
}
// did we find it?
if ((i==0) && (map[i].textureNumber<0)) { // no, no unused texture slots for the placed we are going
// just use any but the currently in use
for (var j=0;j<panoTexturesSrc.length; j++) if (j!=currentTextureNumber) {
// set that newly needed to unsatisfied
map[mapIndices[j]].textureNumber=-1;
map[0].textureNumber=j;
mapIndices[j]=0;
break;
}
}
}
}
//alert ("kmlGot() - 1\n"+panoTexturesSrc[map[0].textureNumber]+"\n"+map[0].href);
if (panoTexturesSrc[map[0].textureNumber]!=map[0].href) {
panoTexturesSrc[map[0].textureNumber]=map[0].href;
//alert ("kmlGot() - 2");
loadTexture(map[0].textureNumber);
} else {
//alert ("kmlGot() - 3");
switchPanorama();
}
createPermanentLink();
// First item is where we came (mnost important
// TODO: make the panorama in the same direction - second important
}
function switchPanorama() {
//alert ("switchPanorama() - 1, settings.transitionTime="+settings.transitionTime+" previousTextureNumber="+previousTextureNumber);
// 1 - launch loading of surrounding panoramas (if any),
// 2 - (re)calculate arrows,
// make step (current texture number
//alert ("switch panorama");
unlockAxis();
loading_intvl=setInterval("loading_blink()",1000);
$("#status").show();
// just testing it here (new panorama was sometimes briefly appearing before transiotion)
if (((settings.transitionTime>0) || (settings.transitionSpeed>0)) && (currentTextureNumber>=0)) {
transitionSeeThrough=1.0;
}
for (var i=0;i<map.length;i++) if ((map[i].textureNumber>=0) && (panoTexturesSrc[map[i].textureNumber]!=map[i].href)){
panoTexturesSrc[map[i].textureNumber]=map[i].href;
loadTexture(map[i].textureNumber); // should load other panos in background
}
var dlat,dlong,lat;
// arrows=Array(map.length-1);
//document.title="map.length="+map.length;
// earthRadius=6378100; //meters
//document.title="";
calcArrows();
//alert ("switchPanorama() - 2");
// calculate panorama rotation matrix according to heading, tilt, roll
previousTextureNumber=currentTextureNumber;
currentTextureNumber=map[0].textureNumber;
previousPanoramaRotationMatrix=panoramaRotationMatrix.dup();
//document.title+=" currentTextureNumber="+currentTextureNumber;
currentTextureWidth= panoImages[map[0].textureNumber][0].width*subDivLong; // all sub-textures are supposed to have the same resolution
currentTextureHeight= panoImages[map[0].textureNumber][0].height*subDivLat;
document.getElementById("idTextureSize").innerHTML=currentTextureWidth+"x"+currentTextureHeight;
// update fovYMin (texture resolution might change)
fovYMin=180*gl.viewportHeight/currentTextureHeight/maximalZoom;
if (fovY < fovYMin) fovY=fovYMin; // got from high-resolution panorama to a low-res one
currentZoom=Math.round(1000*180*gl.viewportHeight/currentTextureHeight/fovY)/1000;
showZoom();
//alert ("switchPanorama() - 3");
recalcHTR();
//alert ("switchPanorama() - 4");
waitForPano=false;
detectOverArrow(lastMouseX,lastMouseY);
if (currentArrow>=-1) document.body.style.cursor="pointer";
else document.body.style.cursor="move";
showProgress(-1); // turn off progress indicator
updateSunAzimuthElevation(); // calls drawScene()
//alert ("switchPanorama() - 5, transitionSeeThrough="+transitionSeeThrough);
setMaxZoom(); // can only be set when texture size is known
// setTimeout ("drawScene()", 100 ); // That works! For some reason Chrome fails first drawScene() after loading new texture.
if (settings.follow && (typeof(lastHeading)!='undefined')) {
transitionDeltaAngle=map[0].heading-lastHeading;
if (transitionDeltaAngle>180) transitionDeltaAngle-=360;
else if (transitionDeltaAngle<-180) transitionDeltaAngle+=360;
//document.title="transition.deltaAngle="+transition.deltaAngle;
} else transitionDeltaAngle=0;
if (((settings.transitionTime>0) || (settings.transitionSpeed>0)) && (previousTextureNumber>=0) &&
((transitionStartLLE.latitude!=transitionEndLLE.latitude) || // no transition if it in the same coordinate (jump to itself, altitude changes by 0.2 m)
(transitionStartLLE.longitude!=transitionEndLLE.longitude)) ) {
map[0].latitude=transitionStartLLE.latitude;
map[0].longitude=transitionStartLLE.longitude;
map[0].altitude=transitionStartLLE.altitude;
calcArrows();
drawScene();
//alert (map[0].latitude+"\n"+map[0].longitude+"\n"+map[0].altitude+"\n");
transitionEndTime=(new Date).getTime()+1000*settings.transitionTime;
transitionSeeThrough=1.0;
// transition.angleLeft=transition.deltaAngle;
// setTimeout ("transitionBetweenPanoramas()", 300 );
setTimeout ("transitionBetweenPanoramas()", 100 );
// requestAnimFrame(transitionBetweenPanoramas, canvas);
// transitionBetweenPanoramas(); // TODO: replace with animate
} else {
// requestAnimFrame(drawScene, canvas);
azimuth+=transitionDeltaAngle;
setTimeout ("drawScene()", 300 ); // That works! For some reason Chrome fails first drawScene() after loading new texture.
}
}
function transitionBetweenPanoramas(){
var lastTransitionSeeThrough=transitionSeeThrough;
transitionSeeThrough=(transitionEndTime- (new Date).getTime())/(1000*settings.transitionTime);
if (transitionSeeThrough<0) transitionSeeThrough=0;
var astep=transitionDeltaAngle* (lastTransitionSeeThrough-transitionSeeThrough);
azimuth+=astep;
// transition.angleLeft-=astep;
// if (settings.follow) {
var newc=(1.0-transitionSeeThrough);
map[0].latitude= (transitionSeeThrough*transitionStartLLE.latitude+ newc*transitionEndLLE.latitude);
map[0].longitude=(transitionSeeThrough*transitionStartLLE.longitude+newc*transitionEndLLE.longitude);
map[0].altitude=(transitionSeeThrough*transitionStartLLE.altitude+newc*transitionEndLLE.altitude);
calcArrows();
// }
drawScene();
// if (transitionSeeThrough>0) setTimeout ("transitionBetweenPanoramas()", 1000*settings.transitionTime/settings.transitionSteps);
// if (transitionSeeThrough>0) requestAnimFrame(transitionBetweenPanoramas, canvas);
if (lastTransitionSeeThrough>0) requestAnimFrame(transitionBetweenPanoramas, canvas);
// if (lastTransitionSeeThrough>0) setTimeout ("transitionBetweenPanoramas()", 100 );
// else azimuth+=transition.angleLeft; // should be 0?
}
function calcArrows() {
arrows=Array(map.length);
arrows[0]={angle:0, // degrees, - direction?
down:0, // meters down
distance:0, // distance
type:"c"}; // "a" - arrow, "c" camera ""
for (var i=1;i<map.length;i++) {
lat=(map[i].latitude+map[0].latitude)/2;
dlat=map[i].latitude-map[0].latitude;
dlong=(map[i].longitude-map[0].longitude)*Math.cos(lat*Math.PI/180);
map[i].azimuth=(180/Math.PI) * Math.atan2(dlong, dlat); // dlong is scaled by cos(dlat)
map[i].distance=Math.PI*earthRadius*Math.sqrt(dlong*dlong+dlat*dlat)/180;
map[i].height=map[i].altitude-map[0].altitude;
arrows[i]={};
if (map[i].distance>settings.as_camera) {
arrows[i].angle=-map[i].azimuth;
arrows[i].down=map[0].aboveGround;
arrows[i].distance= arrows_away; // use map[i].distance when needed?
arrows[i].type='a';
} else {
arrows[i].angle= -map[i].azimuth;
arrows[i].down= -(map[i].height+map[i].aboveGround-map[0].aboveGround);
arrows[i].distance= map[i].distance; // use map[i].distance when needed?
arrows[i].type='c';
}
}
}
function recalcHTR() {
var newRotationMatrix = createRotationMatrix(-map[0].heading, [0, 1, 0]);
newRotationMatrix = newRotationMatrix.x(createRotationMatrix(map[0].tilt-90, [1, 0, 0]));
newRotationMatrix = newRotationMatrix.x(createRotationMatrix(map[0].roll, [0, 0, 1])); ///
panoramaRotationMatrix = newRotationMatrix.x(createRotationMatrix(-90, [0, 1, 0]));
}
var sceneDrawn=false;
var planView;
function place_points(nodes) {
if ((nodes.length==0) || (typeof(nodes[0].latitude)=="undefined")) {
display_error("The route is undefined or does not exist. Please provide the correct route name in the url as '...html?kml=route-name&'");
document.getElementById("idPermanentLink_div").style.display="none";
$("#idSettingsDialog").hide();
webGLStart();
return;
}
/*
for (var i=0;i<nodes.length;i++) {
place_point(nodes[i],i);
}
osm_set_current_position(nodes[0]);
*/
webGLStart();
}
function place_points_nowebgl(nodes) {
if ((nodes.length==0) || (typeof(nodes[0].latitude)=="undefined")) {
display_error("The route is undefined or does not exist. Please provide the correct route name in the url as '...html?kml=route-name&'");
document.getElementById("idPermanentLink_div").style.display="none";
$("#idSettingsDialog").hide();
return;
}
for (var i=0;i<nodes.length;i++) {
place_point(nodes[i],i);
}
osm_set_current_position(nodes[0]);
settings.start = nodes[0].href.substr(nodes[0].href.lastIndexOf('/')+1);
clickedArrow(0);
}
function webGLStart() {
//parseURL();
//applySettings();
resize();
document.body.style.cursor="wait";
// var canvas = document.getElementById("pano-canvas");
canvas = document.getElementById("pano-canvas");
planView = document.getElementById("idPlanView");
initGL(canvas);
initShaders();
initBuffers();
initTextures();
initArrowTexture();
initEyesisTexture();
initSunTexture();
initFootprintsBackpackTexture();
initDotTexture();
var url=serverURL+"?kml="+settings.kml+"&range="+settings.range+"&map=all";
$("#idShowKML").attr("href","display_kml.php?id="+settings.kml);
if (settings.mask!="") url+="&mask="+settings.mask; // use second KML file to overwrite main KML file settings
if (settings.map!="") url+="&map="+settings.map; // specify if full map rebuild is needed (default - sequential) or if interpolation for "visibility=0" is needed
// if (settings.Visibility3d) url+="&v3d";
if ((typeof(settings.view)!="undefined") && (settings.view)) url+="&view"; // force view only mode
if ((typeof(settings.proto)!="undefined") && (settings.proto!="")) url+="&proto="+settings.proto; // use this KML file as a prototype for kml= (copy to kml if kml does not exist)
if (settings.start!="") url+="&href="+settings.start;
requestKml(url,kmlGot);
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clearDepth(1.0);
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
canvas.onmousedown = handleMouseDown;
document.onmouseup = handleMouseUp;
document.onmousemove = handleMouseMove;
document.onkeyup = handleKeyUp;
// if (window.addEventListener)
// window.addEventListener('DOMMouseScroll', wheelEvent, false);
// window.onmousewheel = document.onmousewheel = wheelEvent;
if (canvas.addEventListener) canvas.addEventListener('DOMMouseScroll', wheelEvent, false);
if (planView.addEventListener) planView.addEventListener('DOMMouseScroll', wheelEvent, false);
canvas.onmousewheel = canvas.onmousewheel = wheelEvent;
planView.onmousewheel = wheelEvent;
//TODO: - move elsewhere
document.getElementById("idEditMode").checked=editEnabled;
document.getElementById("idShowPlan").checked=showPlan;
document.getElementById("idShowCams").checked=showCams;
document.getElementById("idClickCams").checked=clickCams;
document.getElementById("idShowLabels").checked=settings.labels;
if (settings.markVisibility3d && settings.edit) document.getElementById("idSelectVisibility").checked=true;
else document.getElementById("idSelectKeyPoints").checked=true;
//idEnableVerticalMove
document.getElementById("idEnableVerticalMove").checked=verticalEnabled;
resize(); // if the table height has changed
}
var margins;
var marginsSet=false;
function resize(){
var frame = document.getElementById("webgl");
if (!marginsSet) {
margins= window.innerWidth-document.getElementById("webgl").offsetWidth;
}
//var height = document.body.clientHeight-document.getElementById("table").offsetHeight-margins; // body margin should be 0 or get current margins from offesWidth
var height = document.body.clientHeight-margins; // body margin should be 0 or get current margins from offesWidth
var width= window.innerWidth-margins;
var windowheight = window.innerHeight;
frame.style.height = height + "px";
frame.style.width = width + "px";
document.getElementById("pano-canvas").style.height = height + "px";
document.getElementById("pano-canvas").style.width = width + "px";
document.getElementById("pano-canvas").height = height;
document.getElementById("pano-canvas").width = width;
document.getElementById("idDivProgressBar").style.top = (height/2+62) + "px";
document.getElementById("idDivProgressBar").style.left = (width/2-62) + "px";
// if (marginsSet) { // firefox crashed sometimes, will disable resize until scene was drawn at least once
if (sceneDrawn) {
gl.viewportWidth = width;
gl.viewportHeight = height;
gl.viewport(0, 0, width, height);
if (settings.keepZoom) {
fovY=180*gl.viewportHeight/currentTextureHeight/currentZoom;
fovYMin=180*gl.viewportHeight/currentTextureHeight/maximalZoom;
if ((fovY < fovYMin) || (fovY > fovYMax)) {
if (fovY < fovYMin) fovY=fovYMin;
if (fovY > fovYMax) fovY=fovYMax;
currentZoom=Math.round(1000*180*gl.viewportHeight/currentTextureHeight/fovY)/1000; // show zoom if it chnaged
showZoom();
}
} else {
fovYMin=180*gl.viewportHeight/currentTextureHeight/maximalZoom;
if (fovY < fovYMin) fovY=fovYMin;
currentZoom=Math.round(1000*180*gl.viewportHeight/currentTextureHeight/fovY)/1000;
showZoom();
}
update_fovY();
drawScene();
}
marginsSet=true;
}
// show progress bar, if neghative - hide
function showProgress (fraction) {
// TODO: place in the center
// document.getElementById("pano-canvas").height = height;
// document.getElementById("pano-canvas").width = width;
var id=document.getElementById("idProgressBar");
if (fraction<0) {
$('#idDivProgressBar').hide();
id.style.display="none";
} else {
id.style.alt=Math.round (fraction*100)+"%";
id.style.backgroundPosition=Math.round (-120+fraction*121)+"px 0px";
id.style.display="";
$('#idDivProgressBar').show();
}
}
function setMaxZoom() {
// var minimalZoom=.01; // relative to texture pixels (calculated from fovYMax)
if (currentTextureHeight<=0) return; // do nothing until defined (at least one texture loaded)
var minimalZoom=180*gl.viewportHeight/currentTextureHeight/fovYMax;
maximalZoom=parseFloat(document.getElementById("idMaxZoom").value);
if (maximalZoom<minimalZoom) {
maximalZoom=0.01*Math.round(100*minimalZoom*2); // at least 2:1 range
document.getElementById("idMaxZoom").value=maximalZoom;
}
fovYMin=180*gl.viewportHeight/currentTextureHeight/maximalZoom;
}
function setZoom() {
// document.title="waszoom="+currentZoom+" was-fovY="+fovY+ " currentTextureHeight="+currentTextureHeight;
currentZoom=parseFloat(document.getElementById("idZoom").value);
fovY=180*gl.viewportHeight/currentTextureHeight/currentZoom;
update_fovY();
// document.title+=" zoom="+currentZoom+" fovY="+fovY;
drawScene();
}
function update_fovY(){
settings.fovy = Math.round(fovY*10)/10;
}
function showZoom() {
document.getElementById("idZoom").value=currentZoom;
}
function changeEditMode(checked) {
editEnabled=checked;
drawScene();
resize(); // if the table height has changed
}
function changeShowCams(checked) {
showCams=checked;
drawScene();
}
function changeClickCams(checked) {
clickCams=checked;
drawScene();
}
function changeShowLabels(checked) {
settings.labels=checked;
drawScene();
}
function changeVerticalMove(checked) {
//idEnableVerticalMove
verticalEnabled=checked;
drawScene();
}
function cloneEyesis(currentArrow) { // copy current camera to pair (ghost/edit, show control fields)
floatingEyesisNum=currentArrow;
floatingEyesis.angle=arrows[currentArrow].angle; // undefioned here
floatingEyesis.down=arrows[currentArrow].down;
floatingEyesis.distance=Math.abs(arrows[currentArrow].distance);
//document.title="floatingEyesisNum="+floatingEyesisNum+" currentArrow="+currentArrow+" arrows[currentArrow].angle="+arrows[currentArrow].angle+" floatingEyesis.angle="+floatingEyesis.angle;
document.getElementById("idModifiedAzimuth").value= -Math.round(100*floatingEyesis.angle)/100;
document.getElementById("idOriginalAzimuth").innerHTML= -Math.round(100*floatingEyesis.angle)/100;
document.getElementById("idModifiedElevation").value= -Math.round(100*floatingEyesis.down)/100;
document.getElementById("idOriginalElevation").innerHTML=-Math.round(100*floatingEyesis.down)/100;
document.getElementById("idModifiedDistance").value= Math.round(100*floatingEyesis.distance)/100;
document.getElementById("idOriginalDistance").innerHTML= Math.round(100*floatingEyesis.distance)/100;
document.getElementById("idFloatingNodeName").innerHTML= map[currentArrow].name;
document.getElementById("idFloatingNodeDescription").innerHTML= map[currentArrow].description;
document.getElementById("idFloatingNodeAttributes").innerHTML= "&nbsp;"+ ((map[currentArrow].visibility!==false)?"Keypoint":"----")+"&nbsp;"+((map[currentArrow].open!==false)?"visible":"hidden");
document.getElementById("idFloatingEyesis").style.display="";
showVisibilityButtons(currentArrow);
drawScene();
//TODO: Create new icon on the map (noo coordinates yet)
updatePositionLLEAndMap(); //TODO: will also move the new icon
document.getElementById("idOriginalCameraLongitude").innerHTML=document.getElementById("idCameraLongitude").innerHTML;
document.getElementById("idOriginalCameraLatitude").innerHTML=document.getElementById("idCameraLatitude").innerHTML;
document.getElementById("idOriginalCameraElevation").innerHTML=document.getElementById("idCameraElevation").innerHTML;
}
function showVisibilityButtons(currentArrow) {
// if (floatingEyesisNum<=0) document.getElementById("idVisibilityHideSeqSpan").style.display="none";
// Or should tghese buttons be shown only when settings.markVisibility3d is set ("ghosts" for invisible, nof for non-key points?)
document.getElementById("idVisibilityHideFarSpan").style.display="none";
document.getElementById("idVisibilityTrimFarSpan").style.display="none";
document.getElementById("idVisibilityShowOneSpan").style.display="none";
document.getElementById("idVisibilityShowSeqSpan").style.display="none";
document.getElementById("idVisibilityHideOneSpan").style.display="none";
document.getElementById("idVisibilityHideSeqSpan").style.display="none";
document.getElementById("idVisibilityClearSpan").style.display="none";
document.title+=" >>"+currentArrow+"<<"+settings.edit+":"+settings.markVisibility3d;
if (!settings.edit || settings.markVisibility3d) document.getElementById("idKeypointButtons").style.display="none";
else document.getElementById("idKeypointButtons").style.display="";
if (!settings.edit || !settings.markVisibility3d) document.getElementById("idVisibilityButtons").style.display="none";
else {
organizeVisibilityRanges();
var index=map[currentArrow].name-map[0].name;
var range=map[0].v3d;
if (currentArrow==0) {
document.getElementById("idVisibilityClearSpan").style.display="";
} else {
var state=locateVisibilityRange(index, range);
//document.title="index="+index+" rIndex="+state.rIndex+" visibility="+state.visibility;
// Hide all, then show needed
if (state.visibility) {
// Is it the range that includes 0?
if (((typeof(range[state.rIndex].from)=='undefined') || (range[state.rIndex].from<0)) &&
((typeof(range[state.rIndex].to)=='undefined') || (range[state.rIndex].to>00))) {
document.getElementById("idVisibilityHideFarSpan").style.display="";
// are there other ranges father than this?
if (((index<0) && (state.rIndex>0)) || ((index>0) && (state.rIndex<(range.length-1)))) {
document.getElementById("idVisibilityTrimFarSpan").style.display="";
}
} else { // not the nearest to 0 range
document.getElementById("idVisibilityHideOneSpan").style.display="";
document.getElementById("idVisibilityHideSeqSpan").style.display="";
}
} else { // selected point is currently invisible
document.getElementById("idVisibilityShowOneSpan").style.display="";
document.getElementById("idVisibilityShowSeqSpan").style.display="";
}
}
document.getElementById("idVisibilityButtons").style.display="";
}
}
function organizeVisibilityRanges(){
if ((typeof(map[0].v3d)=="undefined") ||(map[0].v3d.length==0)){ // convert none visible to all visible
map[0].v3d=[{}]; // all points are visible, from -infinity to +infinity
}
/*
var debugStr="organizeVisibilityRanges() - input:\n";
for (var i=0;i<map[0].v3d.length;i++) {
debugStr+="from:"+map[0].v3d[i].from+" to:"+map[0].v3d[i].to+"\n";
}
alert (debugStr);
*/
// remove wrong (from>to) ranges
var tmp=[];
for (var i=0;i<map[0].v3d.length;i++) {
if ((typeof(map[0].v3d[i].from)=='undefined') ||
(typeof(map[0].v3d[i].to)=='undefined') ||
(map[0].v3d[i].to>=map[0].v3d[i].from)) tmp.push(map[0].v3d[i]);
}
map[0].v3d=tmp;
/*
var debugStr="organizeVisibilityRanges() - removed wrong:\n";
for (var i=0;i<map[0].v3d.length;i++) {
debugStr+="from:"+map[0].v3d[i].from+" to:"+map[0].v3d[i].to+"\n";
}
alert (debugStr);
*/
var ordered=false;
// order existent ranges by lower limits
while (!ordered) {
ordered=true;
for (var i=0;i<(map[0].v3d.length-1);i++) {
if (((typeof(map[0].v3d[i+1].from)=='undefined') && (typeof(map[0].v3d[i].from)!='undefined')) ||
((typeof(map[0].v3d[i+1].from)!='undefined') && (typeof(map[0].v3d[i].from)!='undefined') && (map[0].v3d[i+1].from<map[0].v3d[i].from))) {
var tmp=map[0].v3d[i+1];
map[0].v3d[i+1]=map[0].v3d[i];
map[0].v3d[i]=tmp;
ordered=false;
}
}
}
/*
var debugStr="2:\n";
for (var i=0;i<map[0].v3d.length;i++) {
debugStr+="from:"+map[0].v3d[i].from+" to:"+map[0].v3d[i].to+"\n";
}
alert (debugStr);
*/
// try to merge ranges
var newVis=[map[0].v3d[0]];
for (var i=1;i<map[0].v3d.length;i++) {
if ((typeof(map[0].v3d[i].from)=='undefined') || (typeof(newVis[newVis.length-1].to)=='undefined') || (map[0].v3d[i].from<=(newVis[newVis.length-1].to+1))){
//document.title+=" "+i+"A";
if (typeof(newVis[newVis.length-1].to)!='undefined') {
// merge
//document.title+=" "+i+"B";
if (typeof(map[0].v3d[i].to)=='undefined') delete newVis[newVis.length-1].to;
else if (map[0].v3d[i].to > newVis[newVis.length-1].to) newVis[newVis.length-1].to=map[0].v3d[i].to;
} // if the upper limit was already infinity - no changes in the original when merging
//document.title+=" "+i+"C";
} else {
newVis.push(map[0].v3d[i]); // just copy to the new array
//document.title+=" "+i+"D("+newVis.length+")";
}
}
map[0].v3d=newVis;
// Now the visibility ranges should be ordered and non-overlapping (even not "touching" each other)
// let us verify it works
/*
var debugStr="organizeVisibilityRanges():\n";
for (var i=0;i<map[0].v3d.length;i++) {
debugStr+="from:"+map[0].v3d[i].from+" to:"+map[0].v3d[i].to+"\n";
}
alert (debugStr);
*/
}
// returns a pair of {visibility:true/false, rIndex: range index} (if invisible - rIndex is next towards 0
function locateVisibilityRange(index, // index (map[i].name-map[0].name) to determine visibility range
ranges) { // map[0].vsd -array of ordered ranges ( after organizeVisibilityRanges())
var rIndex;
if (index>0) for (rIndex=ranges.length-1;rIndex>=0;rIndex--) {
if ((typeof(ranges[rIndex].from)=='undefined') || (ranges[rIndex].from <= index)) break;
} else for (rIndex=0; rIndex<ranges.length; rIndex++) { //index<0 (index==0 filtered earlier)
if ((typeof(ranges[rIndex].to)=='undefined') || (ranges[rIndex].to >= index)) break;
}
var visibility=(((typeof(ranges[rIndex].from)=='undefined') || (ranges[rIndex].from<=index)) &&
((typeof(ranges[rIndex].to)== 'undefined') || (ranges[rIndex].to>=index)));
//alert("1 - locateVisibilityRange():\nindex="+index+"\nrIndex="+rIndex+"\nvisibility="+visibility);
/*
if (!visibility) {// make range either include index or be closer to the 0 point
if (index <0) rIndex++;
else rIndex--;
}
*/
//document.title="visibility:"+visibility+" rIndex:"+rIndex;
return {visibility:visibility,rIndex:rIndex};
}
//document.title="index="+index+" rIndex="+state.rIndex+" visibility="+state.visibility;
function set3dVisibility(id) {
var currentArrow=floatingEyesisNum; //global
var index=map[currentArrow].name-map[0].name;
var range=map[0].v3d;
var state=locateVisibilityRange(index, range);
if ((index==0) && (id!="idVisibilityClear")) {
alert ('Error in set3dVisibility() - when editing visibility of self, only "Clear v3d" is possible');
return;
}
switch (id) {
case "idVisibilityClear":range=[{}]; break;
case "idVisibilityHideFar":
// delete all outer ranges, then fall through to "trim"
if (index<0) {
if (state.rIndex>0) {
// invalidate first ranges - they will be removed by organizeVisibilityRanges();
for (var i=0; i<state.rIndex;i++) {
range[i].from=1;
range[i].to=-1;
}
}
} else {
// invalidate last ranges - they will be removed by organizeVisibilityRanges();
if (state.rIndex<(range.length-1)) {
for (var i=state.rIndex+1; i<range.length;i++){
range[i].from=1;
range[i].to=-1;
}
}
}
case "idVisibilityTrimFar":
if (index<0) {
range[state.rIndex].from=index+1; // may become > .to
} else {
range[state.rIndex].to=index-1; // may become < .from
}
break;
case "idVisibilityShowOne":
range.push({from:index,to:index}); // out of order, will need organizeVisibilityRanges();
break;
case "idVisibilityShowSeq":
//document.title="state.rIndex="+state.rIndex+" range.length="+range.length+" index="+index;
if ((index<0) && (state.rIndex==0)) {
delete range[0].from;
} else if (state.rIndex==(range.length-1)) {
delete range[range.length-1].to;
} else { // merge two ranges
if (index<0) state.rIndex--;
range[state.rIndex].to=range[state.rIndex+1].from; // will be actually merged in organizeVisibilityRanges();
}
//document.title="index="+index+" rIndex="+state.rIndex+" length="+(range.length)+" to="+range[state.rIndex].to+" from="+range[state.rIndex].from+" 1to="+range[state.rIndex+1].to+" 1from="+range[state.rIndex+1].from;
break;
case "idVisibilityHideOne":
// spit this range in 2
var newRange={from:index+1};
if (typeof(range[state.rIndex].to)!='undefined') newRange.to=range[state.rIndex].to;
range[state.rIndex].to=index-1;
range.push(newRange);
break;
case "idVisibilityHideSeq":
// just invalidate current range:
range[state.rIndex].from=1;
range[state.rIndex].to=-1;
break;
}
map[0].v3d=range;
organizeVisibilityRanges();
calcVisibility3d(); // update 'open' property form v3d for plan/scene display
// saveFloatingEyesis(); // will draw scene. Or use cancelFloatingEyesis?
cancelFloatingEyesis(); // will draw scene. Or use cancelFloatingEyesis?
// showVisibilityButtons(currentArrow);
// drawScene();
// update information, draw scene, cancel floating Eyesis?
// alert ("Clicked "+id);
}
function changeHighlightMode(id) {
settings.markVisibility3d= (id=="idSelectVisibility");
if (settings.markVisibility3d) {
// alert ("typeof(map[0].v3d)="+typeof(map[0].v3d));
// alert ("map[0].v3d.length="+map[0].v3d.length);
organizeVisibilityRanges();
calcVisibility3d(); // update 'open' property form v3d for plan/scene display
document.getElementById("idKeypointButtons").style.display="none";
//document.title="idKeypointButtons - off";
} else {
document.getElementById("idKeypointButtons").style.display="";
//document.title="idKeypointButtons - on";
}
// if (floatingEyesisNum<=0) document.getElementById("idVisibilityHideSeqSpan").style.display="none";
if (floatingEyesisNum>=0) {
showVisibilityButtons(floatingEyesisNum);
//document.title+=" floatingEyesisNum="+floatingEyesisNum;
}
// if ((floatingEyesisNum>=0) && (!settings.markVisibility3d)) document.getElementById("idKeypointButtons").style.display="";
// else document.getElementById("idKeypointButtons").style.display="none";
drawScene();
}
function cancelFloatingEyesis(){
floatingEyesisNum=-1;
document.getElementById("idFloatingEyesis").style.display="none";
showInformation();
drawScene();
}
function saveFloatingEyesis(){
if (floatingEyesisNum>=0) { // should always be
map[floatingEyesisNum].latitude=floatingEyesisLLE.latitude;
map[floatingEyesisNum].longitude=floatingEyesisLLE.longitude;
map[floatingEyesisNum].altitude=floatingEyesisLLE.altitude;
calcArrows();
}
cancelFloatingEyesis();
}
function updatePositionControlsAndMap() {
document.getElementById("idModifiedAzimuth").value= -Math.round(orientRounding*floatingEyesis.angle)/orientRounding;
document.getElementById("idModifiedElevation").value= -Math.round(altRounding*floatingEyesis.down)/altRounding;
document.getElementById("idModifiedDistance").value= Math.round(altRounding*floatingEyesis.distance)/altRounding;
updatePositionLLEAndMap();
}
function updatePositionLLEAndMap() {
floatingEyesisLLE=calcCameraLLE(floatingEyesis, map[0]);
document.getElementById("idCameraLongitude").innerHTML= Math.round(latLongRounding*floatingEyesisLLE.longitude)/latLongRounding;
document.getElementById("idCameraLatitude").innerHTML= Math.round(latLongRounding*floatingEyesisLLE.latitude)/latLongRounding;
document.getElementById("idCameraElevation").innerHTML= Math.round(altRounding*floatingEyesisLLE.altitude)/altRounding;
//TODO: Update map here (moving icon of one camera - floatingEyesisLLE )
}
function calcCameraLLE(azRelevDist, thisLLE) {
var otherLLE={};
var angle=-Math.PI*azRelevDist.angle/180;
var dLatLong=azRelevDist.distance/earthRadius*180/Math.PI; //distance in degrees (on a big circle connecting map[0] and the camera
var dLat= dLatLong*Math.cos(angle);
var dLong=dLatLong*Math.sin(angle)/Math.cos((thisLLE.latitude+dLat/2)*Math.PI/180);
var dAlt=-azRelevDist.down;
otherLLE.latitude=thisLLE.latitude+dLat;
otherLLE.longitude=thisLLE.longitude+dLong;
otherLLE.altitude=thisLLE.altitude+dAlt;
return otherLLE;
}
function moveEyesis() {
floatingEyesis.angle=-parseFloat(document.getElementById("idModifiedAzimuth").value);
floatingEyesis.down=-parseFloat(document.getElementById("idModifiedElevation").value);
floatingEyesis.distance=parseFloat(document.getElementById("idModifiedDistance").value);
updatePositionLLEAndMap();
drawScene();
}
function sunAzimuthElevation(){
Sun.azimuth=parseFloat(document.getElementById("idSunAzimuth").value);
Sun.elevation=parseFloat(document.getElementById("idSunElevation").value);
drawScene();
}
function updateSunAzimuthElevation(){
// <tr><td>Timestamp:</td><td><span id="idTimeStamp">&nbsp;</span></td> </tr>
document.getElementById("idTimeStamp").innerHTML=
((map[0].time.month<10)?"0":"")+map[0].time.month+"/"+
((map[0].time.day<10)?"0":"")+map[0].time.day+"/"+
map[0].time.year+" "+
((map[0].time.hour<10)?"0":"")+map[0].time.hour+":"+
((map[0].time.minute<10)?"0":"")+map[0].time.minute+":"+
((map[0].time.second<10)?"0":"")+map[0].time.second+" UTC";
/*
function CalcSunPos(latitude, longitude, hh, mm, ss, year, month, day)
return {azimuth:azimuth,elevation:elevation};
*/
//TODO: modify CalcSunPos javascript file to use standard longitude (+E, -W) !!! - DONE
var sunPosition=CalcSunPos(map[0].latitude, map[0].longitude, map[0].time.hour, map[0].time.minute, map[0].time.second, map[0].time.year, map[0].time.month, map[0].time.day) ;
Sun.azimuth=sunPosition.azimuth;
Sun.elevation=sunPosition.elevation;
document.getElementById("idSunAzimuth").value=Math.round(orientRounding*Sun.azimuth)/orientRounding;
document.getElementById("idSunElevation").value=Math.round(orientRounding*Sun.elevation)/orientRounding;
drawScene();
}
function levelView() {
elevation=0.0;
if (showInfo) showInformation();
// setTimeout ("drawScene()", 300 ); // That works! For some reason Chrome fails first drawScene() after loading new texture.
drawScene();
}
function turnView() {
azimuth+=90.0;
if (azimuth>360) azimuth-=360;
if (showInfo) showInformation();
// setTimeout ("drawScene()", 300 ); // That works! For some reason Chrome fails first drawScene() after loading new texture.
drawScene();
}
function parseURL() {
get_filelist();
var parameters=location.href.replace(/\?/ig,"&").split("&");
for (var i=0;i<parameters.length;i++) parameters[i]=parameters[i].split("=");
for (var i=1;i<parameters.length;i++) {
switch (parameters[i][0]) {
// case "edit": settings.edit=true; break;
case "n":
case "ntxt": settings.numTextures=parseInt(parameters[i][1]); break;
case "kml": settings.kml= parameters[i][1]; break;
case "start":settings.start= parameters[i][1]; break;
case "as-camera":
case "as_camera":settings.as_camera= parseFloat(parameters[i][1]); break;
case "range":settings.range= parseFloat(parameters[i][1]); break;
case "labels": if (parameters[i][1]=="true") settings.labels=true; else settings.labels=false; break;
case "keepzoom": if (parameters[i][1]=="true") settings.keepZoom=true; else settings.keepZoom=false; break;
case "closest2d": if (parameters[i][1]=="true") settings.closestIn2d=true; else settings.closestIn2d=false; break;
case "seethrough": settings.seethrough= parseFloat(parameters[i][1]); break;
case "transition": settings.transitionTime= parseFloat(parameters[i][1]); break;
case "speed": settings.transitionSpeed= parseFloat(parameters[i][1]); break;
// case "transition-steps": settings.transitionSteps=parseInt(parameters[i][1]); break;
case "mask": settings.mask=parameters[i][1]; break;
case "map": settings.map=parameters[i][1]; break;
case "follow": if (parameters[i][1]=="true") settings.follow=true; else settings.follow=false; break;
// case "v3d": settings.Visibility3d=true; break;
case "mv3d": if (parameters[i][1]=="true") settings.markVisibility3d=true; else settings.markVisibility3d=false; break;
case "azimuth": azimuth=parseFloat(parameters[i][1]); break;
case "elevation": elevation=parseFloat(parameters[i][1]); break;
case "proto": settings.proto= parameters[i][1]; break;
case "view": settings.view=true; break;
case "fovy": settings.fovy= parameters[i][1]; break;
}
if (settings.numTextures <2) settings.numTextures = 2; // 2 is minimal
if (settings.as_camera> (0.95*worldRadius)) settings.as_camera = 0.95*worldRadius; // will not be visible outside of the sphere
}
if (settings.proto=="") settings.proto = settings.kml;
// alert ('settings.Visibility3d='+settings.Visibility3d);
}
function applySettings() {
setWritableMode(settings.edit);
panoTexturesSrc=Array(settings.numTextures);
panoTextures=Array(panoTexturesSrc.length);
panoImages= Array(panoTexturesSrc.length);
panoLoadedSubTextures= Array(panoTexturesSrc.length);
for (var i=0; i<panoTexturesSrc.length; i++) {
panoTextures[i]=Array(numSubTextures);
panoImages[i]= Array(numSubTextures);
}
mapIndices= Array(panoTexturesSrc.length); // from texture number to node number
showPlan=settings.edit; // edit enable mode is set later, when the kml is read. but show plan should be set just once at startup
disableDragging(document);
$("#seeThroughSlider").val(settings.seethrough*100);
$("#seeThroughInput").val(settings.seethrough);
fovY = settings.fovy;
console.log("Apply Settings: "+fovY);
}
function setWritableMode(enable) {
if (!enable && settings.edit) changeEditMode(false); // turn off edit mode if file is not writeable anymore (unlikely)
var oldEnable=settings.edit;
settings.edit=enable;
$("#idSunAzimuth").attr("disabled",(!settings.edit));
$("#idSunElevation").attr("disabled",(!settings.edit));
var displayWritable=settings.edit?"":"none";
document.getElementById("idShowEditMode").style.display=displayWritable;
document.getElementById("IdSeeThroughTd").style.display=displayWritable;
document.getElementById("idExtraInfo").style.display=displayWritable;
document.getElementById("idSelectHighlightMode").style.display=displayWritable;
document.getElementById("idLongitude").disabled=!settings.edit;
document.getElementById("idLatitude").disabled=!settings.edit;
document.getElementById("idAltitude").disabled=!settings.edit;
document.getElementById("idHeading").disabled=!settings.edit;
document.getElementById("idTilt").disabled=!settings.edit;
document.getElementById("idRoll").disabled=!settings.edit;
document.getElementById("idNodeDescription").disabled=!settings.edit;
if (settings.edit!=oldEnable) {
document.getElementById("idMaxZoom").value=settings.edit?8:1;
resize(); // if the table height has changed
}
}
// related to plan view
function changeShowPlan(checked) {
showPlan=checked;
showPlanView(showPlan);
}
///http://stackoverflow.com/questions/1807334/js-how-to-prevent-the-default-action-on-images-in-browsers
function cancellingEventHandler(evt) {
evt = evt || window.event;
if (evt.preventDefault) {
evt.preventDefault();
} else if (typeof evt.returnValue !== "undefined") {
evt.returnValue = false;
}
return false;
}
function disableDragging(node) {
node.ondragstart = cancellingEventHandler;
node.ondraggesture = cancellingEventHandler;
}
function disableDraggingSelecting(node) {
node.ondragstart = cancellingEventHandler;
node.ondraggesture = cancellingEventHandler;
node.onselectstart = cancellingEventHandler;
}
function setNodeData(id) {
if (floatingEyesisNum==0) { // con not modify map[0] if it is tied to floating Eyesis
showInformation();
return;
}
switch (id) {
case "idLongitude": map[0].longitude=parseFloat(document.getElementById(id).value); break;
case "idLatitude": map[0].latitude= parseFloat(document.getElementById(id).value); break;
case "idAltitude": map[0].altitude= parseFloat(document.getElementById(id).value); break;
case "idNodeDescription": map[0].description= document.getElementById(id).value; break;
case "idKeyPoint": map[0].visibility= document.getElementById(id).checked;break;
}
//document.title="map[0].visibility="+map[0].visibility;
calcArrows();
drawScene();
}
// calculate "open" field in the map, according to map[].v3d array. Only needed when settings.Visibility3d is true (when false, property'open' is read from the kml)
function calcVisibility3d() {
//document.title="";
var thisNodeNumber=map[0].name; //parseInt(map[0].name);
if (typeof(map[0].v3d)=='undefined') for (var i=1; i<map.length;i++) map[i].open=true;
else for (var i=1; i<map.length;i++) {
map[i].open=false;
var otherNodeNumber=map[i].name; //parseInt(map[i].name);
for (var j=0;j<map[0].v3d.length;j++) {
//document.title+=map[0].v3d[j].from+":";
//document.title+=map[0].v3d[j].to+"-";
if (((typeof(map[0].v3d[j].from)=='undefined') || (otherNodeNumber>=(thisNodeNumber+map[0].v3d[j].from))) &&
((typeof(map[0].v3d[j].to) =='undefined') || (otherNodeNumber<=(thisNodeNumber+map[0].v3d[j].to)))) {
map[i].open=true;
break;
}
}
//document.title+=" "+i+":"+map[i].open;
}
}
// foreach ( $world[$this]['v3d'] as $range) {
// if ((!isset ($range['from']) || ($other>=($this+$range['from']))) && (!isset ($range['to']) || ($other<=($this+$range['to'])))) return 1;
function saveToKML() {
if (floatingEyesisNum>=0) saveFloatingEyesis();
postKmlData(settings.kml, generateKML(map));
document.getElementById("idEditMode").checked=false;
changeEditMode(false);
clickedArrow(0); // reload saved file
// alert ("KML saved");
}
/*
* Move nodes that are farther than selected by the vector, move nodes between this (map[0]) and that other proportional to time distance.
* Should be used when all the nodes are selected (range=<large number>), otherwise too far nodes will not be moved
*/
function moveFarNodes() {
if (floatingEyesisNum>=0) {
var altCorr=floatingEyesisLLE.altitude-map[floatingEyesisNum].altitude;
var latCorr=floatingEyesisLLE.latitude-map[floatingEyesisNum].latitude;
var lonCorr=floatingEyesisLLE.longitude-map[floatingEyesisNum].longitude;
var ohref=map[floatingEyesisNum].href;
cancelFloatingEyesis();
var url=serverURL+"?kml="+settings.kml+"&href="+map[0].href+"&range="+settings.range;
if (settings.mask!="") url+="&mask="+settings.mask; // use second KML file to overwrite main KML file settings
if (settings.map!="") url+="&map="+settings.map; // specify if full map rebuild is needed (default - sequential) or if interpolation for "visibility=0" is needed
if ((typeof(settings.proto)!="undefined") && (settings.proto!="")) url+="&proto="+settings.proto; // use this KML file as a prototype for kml= (copy to kml if kml does not exist)
url+="&ohref="+ohref+"&corr-alt="+altCorr+"&corr-lat="+latCorr+"&corr-lon="+lonCorr;
requestKml(url,kmlGot);
return;
}
}
function interpolateRange() {
if (floatingEyesisNum>=0) {
var altCorr=floatingEyesisLLE.altitude-map[floatingEyesisNum].altitude;
var ohref=map[floatingEyesisNum].href;
cancelFloatingEyesis();
var url=serverURL+"?kml="+settings.kml+"&href="+map[0].href+"&range="+settings.range;
if (settings.mask!="") url+="&mask="+settings.mask; // use second KML file to overwrite main KML file settings
if (settings.map!="") url+="&map="+settings.map; // specify if full map rebuild is needed (default - sequential) or if interpolation for "visibility=0" is needed
if ((typeof(settings.proto)!="undefined") && (settings.proto!="")) url+="&proto="+settings.proto; // use this KML file as a prototype for kml= (copy to kml if kml does not exist)
url+="&ohref="+ohref+"&interpolate-range";
requestKml(url,kmlGot);
return;
}
}
function previuosNextNode(forward) { // true - forward, false - backwards
var diff;
var index=0;
var min=-1;
for (var i=1; i<map.length;i++) {
diff=(forward?1:-1)*(map[i].name-map[0].name);
if ((diff>0) && ((min<0) || (min>diff))) {
index=i;
min=diff;
}
}
clickedArrow(index);
}
//http://stackoverflow.com/questions/5605588/how-to-use-requestanimationframe suggested to remove ";"
window.requestAnimFrame = (function() {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(/* function FrameRequestCallback */ callback, /* DOMElement Element */ element) {
window.setTimeout(callback, 1000/60);
};
})();
</script>
</head>
<!--<body onload="webGLStart();" style="margin:0px;" onresize="resize();" onselectstart="cancellingEventHandler();">-->
<body style="margin:0px;" onresize="resize();" onselectstart="cancellingEventHandler();">
<!--small height, so initially there will be no vertical scrollbar -->
<div id="webgl" style="width:100%;height:10px;background-color:grey;z-index:-1">
<!-- <canvas id="pano-canvas" style="border: none;position:absolute; top:0px;left:0px;"></canvas>-->
<canvas id="pano-canvas" style="border: none;z-index:-1;"></canvas>
</div>
<div id="info" style="position:absolute; top:0px;left:0px;z-index:100;">
<div id="idDivProgressBar" style="position:absolute; width:123; height:12;">
<img id="idProgressBar" src="files/percentImage.png" alt="9.5%" style="background: url(files/percentImage_back.png) top left no-repeat; padding: 0; margin: 5px 0 0 0; background-position: -110.315px 0pt; display:none;" />
</div>
</div>
<div id="idLabels"></div>
<div id="idPlanView" style="position:absolute; top:3px;left:3px; width:256; height:256; background: white; display:none;" onmousedown="handlePlanMouseDown(event,-2);" ondragstart="cancellingEventHandler();" ondraggesture="cancellingEventHandler();"
onselectstart="cancellingEventHandler();">&nbsp;</div>
<div id="idInfo" class="gradient">
<div id="idInfo_table">
<table id="table" border="1">
<tr>
<td rowspan="3">
<table>
<tr><td><div style="width:80px;">Longitude,&deg;</div></td><td><input id="idLongitude" size="8" value="0" onChange="setNodeData(this.id);" class="input_field"/></td></tr>
<tr><td> Latutude,&deg;</td><td><input id="idLatitude" size="8" value="0" onChange="setNodeData(this.id);" class="input_field"/></td></tr>
<tr><td> Altitude, <span class="small_text">m</span></td><td><input id="idAltitude" size="8" value="0" onChange="setNodeData(this.id);" class="input_field"/></td></tr>
</table>
</td>
<td rowspan="3">
<table>
<tr><td> Heading,&deg;</td><td><input id="idHeading" size="5" value="0" onChange="inputHTR();" class="input_field"/></td></tr>
<tr><td> Tilt,&deg; </td><td><input id="idTilt" size="5" value="0" onChange="inputHTR();" class="input_field"/></td></tr>
<tr><td> Roll,&deg; </td><td><input id="idRoll" size="5" value="0" onChange="inputHTR();" class="input_field"/></td></tr>
</table>
</td>
<td rowspan="3">
<div>
<table>
<tr><td><div style="width:110px;">View azimuth,&deg;</div></td><td><button id="idViewAzimuth" onclick="turnView();" class="button">0000</button></td></tr>
<tr><td><div style="width:110px;">View elevation,&deg;</div></td><td><button id="idViewElevation" onclick="levelView();" class="button">0000</button></td></tr>
<tr><td><input type="checkbox" id="idOrtho" name="ortho" value="1" checked />Ortho</td><td></td></tr>
</table>
</div>
</td>
<td rowspan="3">
<table>
<tr><td><div style="width:100px;">Texture size:</div></td><td><span id="idTextureSize" style="font-size:12px;" >00000x0000</span></td></tr>
<tr><td><div style="width:100px;">Maximal zoom:</div></td><td><input id="idMaxZoom" size="5" value="1" onChange="setMaxZoom();" class="input_field"/></td></tr>
<tr><td><div style="width:100px;">Current zoom:</div></td><td><input id="idZoom" size="5" value="1" onChange="setZoom();" class="input_field"/></td></tr>
</table>
</td>
<td rowspan="3" valign="top">
<table>
<tr id="idShowEditMode" style="display:none">
<td> <input type="checkbox" id="idEditMode" name="editMode" value="1" onclick="changeEditMode(this.checked);"/>Edit mode</td>
<td> <button id="idSaveToKML" type="button" onclick="saveToKML();" class="button" >Save to KML</button></td>
</tr>
<tr>
<td colspan="2">
<table>
<tr>
<td>
<div style="width:120px;">
<div id="idShowPlan_tip"><input type="checkbox" id="idShowPlan" name="showPlan" value="1" onclick="changeShowPlan(this.checked);"/>Show plan</div>
<div id="idShowCams_tip"><input type="checkbox" id="idShowCams" name="showCams" value="1" onclick="changeShowCams(this.checked);"/>Show cameras</div>
<div id="idClickCams_tip"><input type="checkbox" id="idClickCams" name="clickCams" value="1" onclick="changeClickCams(this.checked);"/>Click cameras</div>
<div id="idShowLabels_tip"><input type="checkbox" id="idShowLabels" name="showLabels" value="1" onclick="changeShowLabels(this.checked);"/>Show labels</div>
</div>
</td>
<td id="idSelectHighlightMode">
<div style="width:120px;">
<input type="checkbox" id="idEnableVerticalMove" name="vertMode" value="1" onclick="changeVerticalMove(this.checked);"/>Vertical move<br/><br/>
<input type="radio" id="idSelectKeyPoints" name="selectHighlightMode" value="keypoints" onclick="changeHighlightMode(this.id);"/>Key points<br/>
<input type="radio" id="idSelectVisibility" name="selectHighlightMode" value="visibility" onclick="changeHighlightMode(this.id);"/>Visibility<br/>
</div>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
<td id="IdSeeThroughTd" rowspan="4" style="display:none;">
<div id="IdSeeThroughDiv">
<input id="seeThroughInput" type="text" class=input_field title="SeeThrough setting" />
<div id="seeThroughSlider" title="SeeThrough setting" ></div>
</div>
</td>
<td rowspan="3" valign="top">
<table>
<tr><td colspan="2"><div style="width:90px;">Timestamp:</div><div style="width:170px;"><span id="idTimeStamp" style="font-size:12px;" >&nbsp;</span></div></td> </tr>
<tr><td><div>Sun Azimuth:</div></td><td><input id="idSunAzimuth" size="5" value="00.0" onchange="sunAzimuthElevation()" class="input_field" /></td> </tr>
<tr><td><div>Sun Elevation:</div></td><td><input id="idSunElevation" size="5" value="00.0" onchange="sunAzimuthElevation()" class="input_field" /></td> </tr>
</table>
</td>
<td rowspan="3" id="idFloatingEyesis" style="display:none;" valign="top" class="gradient" >
<table id="idFloatingEyesis_table" style="font-size:14px;">
<tr>
<td><div style="width:115px;">Camera azimuth</div></td>
<td><input id="idModifiedAzimuth" size="5" value="00.0" onchange="moveEyesis()" class="input_field"/></td>
<td>(<span id="idOriginalAzimuth">00.0</span>)</td>
<td>&nbsp;Lon:</td>
<td><div style="width:160px"><span id="idCameraLongitude" >000.00000</span>&nbsp;(<span id="idOriginalCameraLongitude">000.00000</span>)</div></td>
<td rowspan="4" >
<div style="padding:3px;"><button id="idSaveCameraPosition" type="button" onclick="saveFloatingEyesis();" class="button" >Save</button></div>
<div style="padding:3px;"><button id="idCancelCameraPosition" type="button" onclick="cancelFloatingEyesis();" class="button">Cancel</button></div>
<div>
<span id="idKeypointButtons">
<span id="idCorrectAltitudeSpan"> <br/><button id="idCorrectAltitude" type="button" class="button" onclick="moveFarNodes();" style="width:80px;">Move </button></span>
<span id="idInterpolateRangeSpan"> <br/><button id="idInterpolateRange" type="button" class="button" onclick="interpolateRange();" style="width:80px;">Interpolate</button></span>
</span>
</div>
<div>
<span id="idVisibilityButtons"><!-- Max 2 buttons are visible simultaneously -->
<span id="idVisibilityHideFarSpan"> <br/><button id="idVisibilityHideFar" type="button" class="button" onclick="set3dVisibility(this.id);" style="width:80px;">Hide Far</button></span>
<span id="idVisibilityTrimFarSpan"> <br/><button id="idVisibilityTrimFar" type="button" class="button" onclick="set3dVisibility(this.id);" style="width:80px;">Trim Far</button></span>
<span id="idVisibilityShowOneSpan"> <br/><button id="idVisibilityShowOne" type="button" class="button" onclick="set3dVisibility(this.id);" style="width:80px;">Show This</button></span>
<span id="idVisibilityShowSeqSpan"> <br/><button id="idVisibilityShowSeq" type="button" class="button" onclick="set3dVisibility(this.id);" style="width:85px;">Show Range</button></span>
<span id="idVisibilityHideOneSpan"> <br/><button id="idVisibilityHideOne" type="button" class="button" onclick="set3dVisibility(this.id);" style="width:80px;">Hide This</button></span>
<span id="idVisibilityHideSeqSpan"> <br/><button id="idVisibilityHideSeq" type="button" class="button" onclick="set3dVisibility(this.id);" style="width:80px;">Hide Range</button></span>
<span id="idVisibilityClearSpan"> <br/><br/><button id="idVisibilityClear" type="button" class="button" onclick="set3dVisibility(this.id);" style="width:80px;">Clear v3d</button></span>
</span>
</div>
</td>
</tr>
<tr>
<td>Camera distance, <span style="font-size:10px;">m</span></td><td><input id="idModifiedDistance" size="5" value="00.0" onchange="moveEyesis()" class="input_field" /></td><td>(<span id="idOriginalDistance">00.0</span>m) </td>
<td>&nbsp;Lat:</td><td><span id="idCameraLatitude" >000.00000</span>&nbsp;(<span id="idOriginalCameraLatitude">000.00000</span>)</td>
</tr>
<tr>
<td>Relative elevation, <span style="font-size:10px;">m</span></td><td><input id="idModifiedElevation" size="5" value="00.0" onchange="moveEyesis()" class="input_field" /></td><td>(<span id="idOriginalElevation">00.0</span>m)</td>
<td>&nbsp;Alt:</td><td><span id="idCameraElevation" >000.00</span>m&nbsp;(<span id="idOriginalCameraElevation">000.00</span>m)</td>
</tr>
<tr>
<td>Description:</td>
<td colspan="4"><span id="idFloatingNodeName"></span>:<span id="idFloatingNodeDescription"></span></td>
</tr>
<tr>
<td><span id="idFloatingNodeAttributes"></span></td>
</tr>
</table>
</td>
</tr>
<tr>
</tr>
<tr>
</tr>
<tr>
<td>Description:</td>
<td colspan="2"><span id="idNodeName"></span>:<input id="idNodeDescription" size="45" value="" onChange="setNodeData(this.id);" class="input_field" style="font-size:12px;" /></td>
<td>
Navigation:
<button id="idBack" type="button" class=button onclick="previuosNextNode(false);">&lt;</button>
<button id="idForward" type="button" class=button onclick="previuosNextNode(true);">&gt;</button>
</td>
<td colspan="1">
<span id="idExtraInfo">
Keypoint
<input type="checkbox" id="idKeyPoint" name="keyPoint" value="1" onclick="setNodeData(this.id);"/>
Open
<input type="checkbox" id="idOpenPoint" name="openPoint" value="1" disabled="disabled"/>
</span>
</td>
<td><span id="idLockedAxis" style="display:none;">Rotation axis: <span id="idLockedAxisDirection">000</span><button id="idUnlock" type="button" onclick="unlockAxis();" class="button" >unlock</button></span></td>
</tr>
</table>
</div>
<div id="idInfo_toggle">hide info</div>
<div id="idPermanentLink_div" ></div>
</div>
<div id="idTopRightCorner">
<div id="idViews" class="gradient">Maps</div>
<div id="idSettings" class="gradient">Settings</div>
<div id="idHelp" class="gradient">?</div>
</div>
<div id="idDialogs">
<div id="idViewsDialog" class="gradient" hidden >
<table>
<tr><td><input id="idOSMap_checkbox" type="checkbox"></td><td>Open Street maps</td></tr>
</table>
</div>
<div id="idSettingsDialog" class="gradient" hidden >
<div title="Enable Edit Mode">
</div>
<div>
<table style="padding:0px">
<tr id="idSettingsEdit_tip" ><td>Edit Mode </td><td><input type="checkbox" id="idSettingsEdit" disabled></td></tr>
<!--<tr id="idSettingsProto_tip" ><td>KML prototype</td><td><input type="text" class=input_field id="idSettingsProto" /></td></tr>-->
<!--<tr id="idSettingsProto_tip"><td>KML prototypes list</td><td><div id="kml_proto_list" class="list"></div></td></tr>-->
<!--<tr id="idSettingsKml_tip" ><td>KML file </td><td><input type="text" class=input_field id="idSettingsKml" /></td></tr>-->
<!--<tr id="idSettingsMask_tip" ><td>KML mask file </td><td><input type="text" class=input_field id="idSettingsMask" /></td></tr>-->
<!--<tr id="idSettingsMask_tip"><td>KML masks list</td><td><div id="kml_mask_list" class="list"></div></td></tr>-->
<!--<tr id="idSettingsMap_tip" ><td>Map build/display </td><td><div id="idSettingsMap" class="list"></div></td></tr>-->
<tr id="idSettingsView_tip" ><td>Force View Mode </td><td><input type="checkbox" id="idSettingsView"></td></tr>
<tr id="idSettingsStart_tip" ><td>Start node name </td><td><input type="text" class=input_field id="idSettingsStart" /></td></tr>
<!-- <tr id="idSettingsMap_tip" ><td>Map build/display </td><td><input type="text" class=input_field id="idSettingsMap" /></td></tr>-->
<tr id="idSettingsRange_tip" ><td>Nodes range, <span style="font-size:10px;">m</span> </td><td><input type="text" class=input_field id="idSettingsRange" /></td></tr>
<tr id="idSettingsAsCamera_tip" ><td>Close icon range, <span style="font-size:10px;">m</span> </td><td><input type="text" class=input_field id="idSettingsAsCamera" /></td></tr>
<tr id="idSettingsNumTextures_tip" ><td>Number of textures</td><td><input type="text" class=input_field id="idSettingsNumTextures" disabled /></td></tr>
<tr id="idSettingsLabels_tip" ><td>Labels </td><td><input type="checkbox" id="idSettingsLabels"></td></tr>
<tr id="idSettingsClosestIn2D_tip" ><td>Closest in 2D </td><td><input type="checkbox" id="idSettingsClosestIn2D"></td></tr>
<tr id="idSettingsKeepZoom_tip" ><td>Keep zoom </td><td><input type="checkbox" id="idSettingsKeepZoom"></td></tr>
<tr id="idSettingsSeeThrough_tip" ><td>See through </td><td><input type="text" class=input_field id="idSettingsSeeThrough" /></td></tr>
<tr id="idSettingsTransitionTime_tip"><td>Transition time </td><td><input type="text" class=input_field id="idSettingsTransitionTime" /></td></tr>
<tr id="idSettingsFollow_tip" ><td>Follow </td><td><input type="checkbox" id="idSettingsFollow"></td></tr>
<!--<tr><td>Visibility3d </td><td><input type="checkbox" id="idSettingsVisibility3d"></td></tr>-->
<tr id="idSettingsMarkVisibility3d_tip"><td>MarkVisibility3d </td><td><input type="checkbox" id="idSettingsMarkVisibility3d"></td></tr>
<tr id="idDisplayKML_tip"><td><a id="idShowKML">Show current route's KML file</a></td></tr>
<!-- <tr><td>Transition steps </td><td><input type="text" class=input_field id="idSettingsTransitionSteps" /></td></tr>-->
<!-- <tr id="idSettingsPlan_tip"><td><b>Plan:</b></td></tr>
<tr id="idSettingsDotSize_tip">
<td>Dot size, <span style="font-size:10px;">px</span></td>
<td><input type="text" class=input_field id="idSettingsDotSize" /></td>
</tr>
<tr id="idSettingsThisColor_tip">
<td>This color</td>
<td>
<table style="padding:0px">
<tr>
<td><input type="text" class=input_field id="idSettingsThisColor" /></td>
<td><div id="idSettingsThisColorSample" class=small_square ></div></td>
</tr>
</table>
</td>
</tr>
<tr id="idSettingsColor_tip">
<td>Color</td>
<td>
<table>
<tr>
<td><input type="text" class=input_field id="idSettingsColor" /></td>
<td><div id="idSettingsColorSample" class=small_square ></div></td>
</tr>
</table>
</td>
</tr>
<tr id="idSettingsSelectedColor_tip">
<td>Selected color</td>
<td>
<table>
<tr>
<td><input type="text" class=input_field id="idSettingsSelectedColor" /></td>
<td><div id="idSettingsSelectedColorSample" class=small_square ></div></td>
</tr>
</table>
</td>
</tr>
<tr id="idSettingsGhostColor_tip">
<td>Ghost color</td>
<td>
<table>
<tr>
<td><input type="text" class=input_field id="idSettingsGhostColor" /></td>
<td><div id="idSettingsGhostColorSample" class=small_square ></div></td>
</tr>
</table>
</td>
</tr>
<tr id="idSettingsInvisibleColor_tip">
<td>Invisible color </td>
<td>
<table>
<tr>
<td><input type="text" class=input_field id="idSettingsInvisibleColor" /></td>
<td><div id="idSettingsInvisibleColorSample" class=small_square ></div></td>
</tr>
</table>
</td>
</tr>-->
</table>
</div>
<div>
<div id="idSettingsDialogOkButton" class="button" style="margin:2px;" >Apply</div>
<div id="idSettingsDialogCancelButton" class="button" style="margin:2px;" >Cancel</div>
</div>
</div>
</div>
<div id="idHelpDialog" class="gradient" hidden >
<div><b style='font-size:16px;'>View Mode</b></div>
<div id="idViewMode_Controls"></div><br/>
<div><b style='font-size:16px;'>Edit Mode</b></div>
<div id="idEditMode_Controls"></div>
</div>
<div id="error_no_webgl" hidden></div>
<div id="all_wrap">
<div id="osmap_wrap">
<div id="osmap_div" class="gradient"><div id="osmap"></div></div>
</div>
</div>
<div id=status style="font-size:60px;position:absolute;padding:20px;width:200px;height:80px;" ></div>
<script>
$('#error_no_webgl').css({background:'white', position:'absolute',top:'600px',left:'600px', padding:'50px'});
$('#error_no_webgl').html("Could not initialise WebGL. Please, check the <a href='http://www.khronos.org/webgl/wiki/Getting_a_WebGL_Implementation'>supported browsers</a>.");
</script>
<!--oleg-->
<script>
parseURL();
applySettings();
//resize();
</script>
<script>
var zoom = 13;
var currentPosition;
var osm_CurrentMarker;
var marker;
var loading_intvl;
pre_loading_blink();
//loading_intvl=setInterval("loading_blink()",1000);
var map_flag = 0;
var osmap_flag = 0;
var info_flag = 0;
translate_request("en");
$("#idInfo_toggle").click();
if (!no_connection) {
osm_init();
initialize_maps();
}else{
$("#idOSMap_checkbox").attr("disabled",true);
$("#idOSMap_checkbox").attr("checked",false);
$("#idViews").hide();
webGLStart();
}
if (!$("#idOSMap_checkbox").attr("checked")) $("#osmap_div").hide();
</script>
</body>
</html>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment