@ -1,208 +0,0 @@ | |||
/** | |||
* Jake build script | |||
*/ | |||
var jake = require('jake'), | |||
browserify = require('browserify'), | |||
wrench = require('wrench'), | |||
CleanCSS = require('clean-css'), | |||
fs = require('fs'); | |||
require('jake-utils'); | |||
// constants | |||
var DIST = './dist'; | |||
var VIS = DIST + '/vis.js'; | |||
var VIS_CSS = DIST + '/vis.css'; | |||
var VIS_TMP = DIST + '/vis.js.tmp'; | |||
var VIS_MIN = DIST + '/vis.min.js'; | |||
var VIS_MIN_CSS = DIST + '/vis.min.css'; | |||
/** | |||
* default task | |||
*/ | |||
desc('Default task: build all libraries'); | |||
task('default', ['build', 'minify'], function () { | |||
console.log('done'); | |||
}); | |||
/** | |||
* build the visualization library vis.js | |||
*/ | |||
desc('Build the visualization library vis.js'); | |||
task('build', {async: true}, function () { | |||
jake.mkdirP(DIST); | |||
jake.mkdirP(DIST + '/img'); | |||
// concatenate and stringify the css files | |||
concat({ | |||
src: [ | |||
'./src/timeline/component/css/timeline.css', | |||
'./src/timeline/component/css/panel.css', | |||
'./src/timeline/component/css/labelset.css', | |||
'./src/timeline/component/css/itemset.css', | |||
'./src/timeline/component/css/item.css', | |||
'./src/timeline/component/css/timeaxis.css', | |||
'./src/timeline/component/css/currenttime.css', | |||
'./src/timeline/component/css/customtime.css', | |||
'./src/timeline/component/css/animation.css', | |||
'./src/timeline/component/css/dataaxis.css', | |||
'./src/timeline/component/css/pathStyles.css', | |||
'./src/network/css/network-manipulation.css', | |||
'./src/network/css/network-navigation.css' | |||
], | |||
dest: VIS_CSS, | |||
separator: '\n' | |||
}); | |||
console.log('created ' + VIS_CSS); | |||
// concatenate the script files | |||
concat({ | |||
dest: VIS_TMP, | |||
src: [ | |||
'./src/module/imports.js', | |||
'./src/shim.js', | |||
'./src/util.js', | |||
'./src/DOMutil.js', | |||
'./src/DataSet.js', | |||
'./src/DataView.js', | |||
'./src/timeline/component/GraphGroup.js', | |||
'./src/timeline/component/Legend.js', | |||
'./src/timeline/component/DataAxis.js', | |||
'./src/timeline/component/LineGraph.js', | |||
'./src/timeline/DataStep.js', | |||
'./src/timeline/Stack.js', | |||
'./src/timeline/TimeStep.js', | |||
'./src/timeline/Range.js', | |||
'./src/timeline/component/Component.js', | |||
'./src/timeline/component/TimeAxis.js', | |||
'./src/timeline/component/CurrentTime.js', | |||
'./src/timeline/component/CustomTime.js', | |||
'./src/timeline/component/ItemSet.js', | |||
'./src/timeline/component/item/*.js', | |||
'./src/timeline/component/Group.js', | |||
'./src/timeline/Timeline.js', | |||
'./src/timeline/Graph2d.js', | |||
'./src/network/dotparser.js', | |||
'./src/network/shapes.js', | |||
'./src/network/Node.js', | |||
'./src/network/Edge.js', | |||
'./src/network/Popup.js', | |||
'./src/network/Groups.js', | |||
'./src/network/Images.js', | |||
'./src/network/networkMixins/physics/PhysicsMixin.js', | |||
'./src/network/networkMixins/physics/HierarchialRepulsion.js', | |||
'./src/network/networkMixins/physics/BarnesHut.js', | |||
'./src/network/networkMixins/physics/Repulsion.js', | |||
'./src/network/networkMixins/HierarchicalLayoutMixin.js', | |||
'./src/network/networkMixins/ManipulationMixin.js', | |||
'./src/network/networkMixins/SectorsMixin.js', | |||
'./src/network/networkMixins/ClusterMixin.js', | |||
'./src/network/networkMixins/SelectionMixin.js', | |||
'./src/network/networkMixins/NavigationMixin.js', | |||
'./src/network/networkMixins/MixinLoader.js', | |||
'./src/network/Network.js', | |||
'./src/graph3d/Graph3d.js', | |||
'./src/module/exports.js' | |||
], | |||
separator: '\n' | |||
}); | |||
// copy images | |||
wrench.copyDirSyncRecursive('./src/network/img', DIST + '/img/network', { | |||
forceDelete: true | |||
}); | |||
wrench.copyDirSyncRecursive('./src/timeline/img', DIST + '/img/timeline', { | |||
forceDelete: true | |||
}); | |||
var timeStart = Date.now(); | |||
// bundle the concatenated script and dependencies into one file | |||
var b = browserify(); | |||
b.add(VIS_TMP); | |||
b.bundle({ | |||
standalone: 'vis' | |||
}, function (err, code) { | |||
if(err) { | |||
throw err; | |||
} | |||
console.log("browserify",Date.now() - timeStart); timeStart = Date.now(); | |||
// add header and footer | |||
var lib = read('./src/module/header.js') + code; | |||
// write bundled file | |||
write(VIS, lib); | |||
console.log('created js' + VIS); | |||
// remove temporary file | |||
fs.unlinkSync(VIS_TMP); | |||
// update version number and stuff in the javascript files | |||
replacePlaceholders(VIS); | |||
complete(); | |||
}); | |||
}); | |||
/** | |||
* minify the visualization library vis.js | |||
*/ | |||
desc('Minify the visualization library vis.js'); | |||
task('minify', {async: true}, function () { | |||
// minify javascript | |||
minify({ | |||
src: VIS, | |||
dest: VIS_MIN, | |||
header: read('./src/module/header.js') | |||
}); | |||
// update version number and stuff in the javascript files | |||
replacePlaceholders(VIS_MIN); | |||
console.log('created minified ' + VIS_MIN); | |||
var minified = new CleanCSS().minify(read(VIS_CSS)); | |||
write(VIS_MIN_CSS, minified); | |||
console.log('created minified ' + VIS_MIN_CSS); | |||
}); | |||
/** | |||
* test task | |||
*/ | |||
desc('Test the library'); | |||
task('test', function () { | |||
// TODO: use a testing suite for testing: nodeunit, mocha, tap, ... | |||
var filelist = new jake.FileList(); | |||
filelist.include([ | |||
'./test/**/*.js' | |||
]); | |||
var files = filelist.toArray(); | |||
files.forEach(function (file) { | |||
require('./' + file); | |||
}); | |||
console.log('Executed ' + files.length + ' test files successfully'); | |||
}); | |||
/** | |||
* replace version, date, and name placeholders in the provided file | |||
* @param {String} filename | |||
*/ | |||
var replacePlaceholders = function (filename) { | |||
replace({ | |||
replacements: [ | |||
{pattern: '@@date', replacement: today()}, | |||
{pattern: '@@version', replacement: version()} | |||
], | |||
src: filename | |||
}); | |||
}; |
@ -0,0 +1,75 @@ | |||
<!doctype html> | |||
<html> | |||
<head> | |||
<title>Network | Static smooth curves</title> | |||
<script type="text/javascript" src="../../dist/vis.js"></script> | |||
<style type="text/css"> | |||
#mynetwork { | |||
width: 400px; | |||
height: 400px; | |||
border: 1px solid lightgray; | |||
} | |||
</style> | |||
</head> | |||
<body> | |||
<h2>Static smooth curves</h2> | |||
<div style="width:700px; font-size:14px;"> | |||
All the smooth curves in the examples so far have been using dynamic smooth curves. This means that each curve has a | |||
support node which takes part in the physics simulation. For large networks or dense clusters, this may not be the ideal | |||
solution. To solve this, static smooth curves have been added. The static smooth curves are based only on the positions of the connected | |||
nodes. There are multiple ways to determine the way this curve is drawn. This example shows the effect of the different | |||
types. <br /> <br /> | |||
Drag the nodes around each other to see how the smooth curves are drawn for each setting. For animated system, we | |||
recommend only the continuous mode. In the next example you can see the effect of these methods on a large network. Keep in mind | |||
that the direction (the from and to) of the curve matters. | |||
<br /> <br /> | |||
</div> | |||
Smooth curve type: | |||
<select id="dropdownID"> | |||
<option value="continuous">continuous</option> | |||
<option value="discrete">discrete</option> | |||
<option value="diagonalCross">diagonalCross</option> | |||
<option value="straightCross">straightCross</option> | |||
<option value="horizontal">horizontal</option> | |||
<option value="vertical">vertical</option> | |||
</select> | |||
<div id="mynetwork"></div> | |||
<script type="text/javascript"> | |||
var dropdown = document.getElementById("dropdownID"); | |||
dropdown.onchange = update; | |||
// create an array with nodes | |||
var nodes = [ | |||
{id: 1, label: 'Node 1'}, | |||
{id: 2, label: 'Node 2', x:150, y:130, allowedToMoveX: true, allowedToMoveY: true} | |||
]; | |||
// create an array with edges | |||
var edges = [ | |||
{from: 1, to: 2} | |||
]; | |||
// create a network | |||
var container = document.getElementById('mynetwork'); | |||
var data = { | |||
nodes: nodes, | |||
edges: edges | |||
}; | |||
var options = {physics:{barnesHut:{gravitationalConstant:0, springConstant:0, centralGravity: 0}}, | |||
smoothCurves:{dynamic:false, type: '1'}}; | |||
var network = new vis.Network(container, data, options); | |||
function update() { | |||
var type = dropdown.value; | |||
network.setOptions({smoothCurves:{type:type}}); | |||
} | |||
</script> | |||
</body> | |||
</html> |
@ -0,0 +1,166 @@ | |||
<!DOCTYPE html> | |||
<!-- saved from url=(0044)http://kenedict.com/networks/worldcup14/vis/ , thanks Andre!--> | |||
<html><head><meta http-equiv="content-type" content="text/html; charset=UTF8"> | |||
<title>Dynamic Data - Importing from Gephi (JSON)</title> | |||
<script type="text/javascript" src="../../dist/vis.js"></script> | |||
<link type="text/css" rel="stylesheet" href="../../dist/vis.css"> | |||
<style type="text/css"> | |||
#mynetwork { | |||
width: 800px; | |||
height: 800px; | |||
border: 1px solid lightgray; | |||
} | |||
div.nodeContent { | |||
position: relative; | |||
border: 1px solid lightgray; | |||
width:480px; | |||
height:780px; | |||
margin-top: -802px; | |||
margin-left: 810px; | |||
padding:10px; | |||
} | |||
pre {padding: 5px; margin: 5px; } | |||
.string { color: green; } | |||
.number { color: darkorange; } | |||
.boolean { color: blue; } | |||
.null { color: magenta; } | |||
.key { color: red; } | |||
</style> | |||
</head> | |||
<body> | |||
<h2>Dynamic Data - Importing from Gephi (JSON)</h2> | |||
<div style="width:700px; font-size:14px;"> | |||
This example shows how to import a JSON file exported by Gephi. The two options available for the import are | |||
available through the checkboxes. You can download the Gephi JSON exporter here: | |||
<a href="https://marketplace.gephi.org/plugin/json-exporter/" target="_blank">https://marketplace.gephi.org/plugin/json-exporter/</a>. | |||
All of Gephi's attributes are also contained within the node elements. This means you can access all of this data through the DataSet. | |||
<br /> | |||
</div> | |||
<input type="checkbox" id="allowedToMove">: Allow to move after import. <br/> | |||
<input type="checkbox" id="parseColor">: Parse the color instead of copy (adds borders, highlights etc.) | |||
<div id="mynetwork"></div> | |||
<div class="nodeContent"><h4>Node Content:</h4> <pre id="nodeContent"></pre></div> | |||
<script type="text/javascript"> | |||
var network; | |||
var nodes = new vis.DataSet(); | |||
var edges = new vis.DataSet(); | |||
var gephiImported; | |||
var allowedToMoveCheckbox = document.getElementById("allowedToMove"); | |||
allowedToMoveCheckbox.onchange = redrawAll; | |||
var parseColorCheckbox = document.getElementById("parseColor"); | |||
parseColorCheckbox.onchange = redrawAll; | |||
var nodeContent = document.getElementById("nodeContent"); | |||
loadJSON("./data/WorldCup2014.json",redrawAll); | |||
var container = document.getElementById('mynetwork'); | |||
var data = { | |||
nodes: nodes, | |||
edges: edges | |||
}; | |||
var options = { | |||
nodes: { | |||
shape: 'dot', | |||
fontFace: "Tahoma" | |||
}, | |||
edges: { | |||
width: 0.15, | |||
inheritColor: "from" | |||
}, | |||
tooltip: { | |||
delay: 200, | |||
fontSize: 12, | |||
color: { | |||
background: "#fff" | |||
} | |||
}, | |||
smoothCurves: {dynamic:false, type: "continuous"}, | |||
stabilize: false, | |||
physics: {barnesHut: {gravitationalConstant: -10000, springConstant: 0.002, springLength: 150}}, | |||
hideEdgesOnDrag: true | |||
}; | |||
network = new vis.Network(container, data, options); | |||
/** | |||
* This function fills the DataSets. These DataSets will update the network. | |||
*/ | |||
function redrawAll(gephiJSON) { | |||
if (gephiJSON.nodes === undefined) { | |||
gephiJSON = gephiImported; | |||
} | |||
else { | |||
gephiImported = gephiJSON; | |||
} | |||
nodes.clear(); | |||
edges.clear(); | |||
var allowedToMove = allowedToMoveCheckbox.checked; | |||
var parseColor = parseColorCheckbox.checked; | |||
var parsed = vis.network.gephiParser.parseGephi(gephiJSON, {allowedToMove:allowedToMove, parseColor:parseColor}); | |||
// add the parsed data to the DataSets. | |||
nodes.add(parsed.nodes); | |||
edges.add(parsed.edges); | |||
var data = nodes.get(2); // get the data from node 2 | |||
nodeContent.innerHTML = syntaxHighlight(data); // show the data in the div | |||
network.zoomExtent(); // zoom to fit | |||
} | |||
// from http://stackoverflow.com/questions/4810841/how-can-i-pretty-print-json-using-javascript | |||
function syntaxHighlight(json) { | |||
if (typeof json != 'string') { | |||
json = JSON.stringify(json, undefined, 2); | |||
} | |||
json = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>'); | |||
return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) { | |||
var cls = 'number'; | |||
if (/^"/.test(match)) { | |||
if (/:$/.test(match)) { | |||
cls = 'key'; | |||
} else { | |||
cls = 'string'; | |||
} | |||
} else if (/true|false/.test(match)) { | |||
cls = 'boolean'; | |||
} else if (/null/.test(match)) { | |||
cls = 'null'; | |||
} | |||
return '<span class="' + cls + '">' + match + '</span>'; | |||
}); | |||
} | |||
function loadJSON(path, success, error) { | |||
var xhr = new XMLHttpRequest(); | |||
xhr.onreadystatechange = function() { | |||
if (xhr.readyState === 4) { | |||
if (xhr.status === 200) { | |||
success(JSON.parse(xhr.responseText)); | |||
} | |||
else { | |||
error(xhr); | |||
} | |||
} | |||
}; | |||
xhr.open("GET", path, true); | |||
xhr.send(); | |||
} | |||
</script> | |||
</body></html> |
@ -0,0 +1,152 @@ | |||
var fs = require('fs'); | |||
var gulp = require('gulp'); | |||
var gutil = require('gulp-util'); | |||
var concat = require('gulp-concat'); | |||
var minifyCSS = require('gulp-minify-css'); | |||
var rename = require("gulp-rename"); | |||
var webpack = require('webpack'); | |||
var uglify = require('uglify-js'); | |||
var rimraf = require('rimraf'); | |||
var merge = require('merge-stream'); | |||
var argv = require('yargs').argv; | |||
var ENTRY = './index.js'; | |||
var HEADER = './lib/header.js'; | |||
var DIST = './dist'; | |||
var VIS_JS = 'vis.js'; | |||
var VIS_MAP = 'vis.map'; | |||
var VIS_MIN_JS = 'vis.min.js'; | |||
var VIS_CSS = 'vis.css'; | |||
var VIS_MIN_CSS = 'vis.min.css'; | |||
// generate banner with today's date and correct version | |||
function createBanner() { | |||
var today = gutil.date(new Date(), 'yyyy-mm-dd'); // today, formatted as yyyy-mm-dd | |||
var version = require('./package.json').version; | |||
return String(fs.readFileSync(HEADER)) | |||
.replace('@@date', today) | |||
.replace('@@version', version); | |||
} | |||
var bannerPlugin = new webpack.BannerPlugin(createBanner(), { | |||
entryOnly: true, | |||
raw: true | |||
}); | |||
// TODO: the moment.js language files should be excluded by default (they are quite big) | |||
var webpackConfig = { | |||
entry: ENTRY, | |||
output: { | |||
library: 'vis', | |||
libraryTarget: 'umd', | |||
path: DIST, | |||
filename: VIS_JS, | |||
sourcePrefix: ' ' | |||
}, | |||
// exclude requires of moment.js language files | |||
module: { | |||
wrappedContextRegExp: /$^/ | |||
}, | |||
plugins: [ bannerPlugin ], | |||
cache: true | |||
}; | |||
var uglifyConfig = { | |||
outSourceMap: VIS_MAP, | |||
output: { | |||
comments: /@license/ | |||
} | |||
}; | |||
// create a single instance of the compiler to allow caching | |||
var compiler = webpack(webpackConfig); | |||
// clean the dist/img directory | |||
gulp.task('clean', function (cb) { | |||
rimraf(DIST + '/img', cb); | |||
}); | |||
gulp.task('bundle-js', ['clean'], function (cb) { | |||
// update the banner contents (has a date in it which should stay up to date) | |||
bannerPlugin.banner = createBanner(); | |||
compiler.run(function (err, stats) { | |||
if (err) gutil.log(err); | |||
cb(); | |||
}); | |||
}); | |||
// bundle and minify css | |||
gulp.task('bundle-css', ['clean'], function () { | |||
var files = [ | |||
'./lib/timeline/component/css/timeline.css', | |||
'./lib/timeline/component/css/panel.css', | |||
'./lib/timeline/component/css/labelset.css', | |||
'./lib/timeline/component/css/itemset.css', | |||
'./lib/timeline/component/css/item.css', | |||
'./lib/timeline/component/css/timeaxis.css', | |||
'./lib/timeline/component/css/currenttime.css', | |||
'./lib/timeline/component/css/customtime.css', | |||
'./lib/timeline/component/css/animation.css', | |||
'./lib/timeline/component/css/dataaxis.css', | |||
'./lib/timeline/component/css/pathStyles.css', | |||
'./lib/network/css/network-manipulation.css', | |||
'./lib/network/css/network-navigation.css' | |||
]; | |||
return gulp.src(files) | |||
.pipe(concat(VIS_CSS)) | |||
.pipe(gulp.dest(DIST)) | |||
// TODO: nicer to put minifying css in a separate task? | |||
.pipe(minifyCSS()) | |||
.pipe(rename(VIS_MIN_CSS)) | |||
.pipe(gulp.dest(DIST)); | |||
}); | |||
gulp.task('copy', ['clean'], function () { | |||
var network = gulp.src('./lib/network/img/**/*') | |||
.pipe(gulp.dest(DIST + '/img/network')); | |||
var timeline = gulp.src('./lib/timeline/img/**/*') | |||
.pipe(gulp.dest(DIST + '/img/timeline')); | |||
return merge(network, timeline); | |||
}); | |||
gulp.task('minify', ['bundle-js'], function (cb) { | |||
var result = uglify.minify([DIST + '/' + VIS_JS], uglifyConfig); | |||
fs.writeFileSync(DIST + '/' + VIS_MIN_JS, result.code); | |||
fs.writeFileSync(DIST + '/' + VIS_MAP, result.map); | |||
cb(); | |||
}); | |||
gulp.task('bundle', ['bundle-js', 'bundle-css', 'copy']); | |||
// read command line arguments --bundle and --minify | |||
var bundle = 'bundle' in argv; | |||
var minify = 'minify' in argv; | |||
var watchTasks = []; | |||
if (bundle || minify) { | |||
// do bundling and/or minifying only when specified on the command line | |||
watchTasks = []; | |||
if (bundle) watchTasks.push('bundle'); | |||
if (minify) watchTasks.push('minify'); | |||
} | |||
else { | |||
// by default, do both bundling and minifying | |||
watchTasks = ['bundle', 'minify']; | |||
} | |||
// The watch task (to automatically rebuild when the source code changes) | |||
gulp.task('watch', watchTasks, function () { | |||
gulp.watch(['index.js', 'lib/**/*'], watchTasks); | |||
}); | |||
// The default task (called when you run `gulp`) | |||
gulp.task('default', ['clean', 'bundle', 'minify']); |
@ -0,0 +1,69 @@ | |||
// utils | |||
exports.util = require('./lib/util'); | |||
exports.DOMutil = require('./lib/DOMutil'); | |||
// data | |||
exports.DataSet = require('./lib/DataSet'); | |||
exports.DataView = require('./lib/DataView'); | |||
// Graph3d | |||
exports.Graph3d = require('./lib/graph3d/Graph3d'); | |||
exports.graph3d = { | |||
Camera: require('./lib/graph3d/Camera'), | |||
Filter: require('./lib/graph3d/Filter'), | |||
Point2d: require('./lib/graph3d/Point2d'), | |||
Point3d: require('./lib/graph3d/Point3d'), | |||
Slider: require('./lib/graph3d/Slider'), | |||
StepNumber: require('./lib/graph3d/StepNumber') | |||
}; | |||
// Timeline | |||
exports.Timeline = require('./lib/timeline/Timeline'); | |||
exports.Graph2d = require('./lib/timeline/Graph2d'); | |||
exports.timeline = { | |||
DataStep: require('./lib/timeline/DataStep'), | |||
Range: require('./lib/timeline/Range'), | |||
stack: require('./lib/timeline/Stack'), | |||
TimeStep: require('./lib/timeline/TimeStep'), | |||
components: { | |||
items: { | |||
Item: require('./lib/timeline/component/item/Item'), | |||
ItemBox: require('./lib/timeline/component/item/ItemBox'), | |||
ItemPoint: require('./lib/timeline/component/item/ItemPoint'), | |||
ItemRange: require('./lib/timeline/component/item/ItemRange') | |||
}, | |||
Component: require('./lib/timeline/component/Component'), | |||
CurrentTime: require('./lib/timeline/component/CurrentTime'), | |||
CustomTime: require('./lib/timeline/component/CustomTime'), | |||
DataAxis: require('./lib/timeline/component/DataAxis'), | |||
GraphGroup: require('./lib/timeline/component/GraphGroup'), | |||
Group: require('./lib/timeline/component/Group'), | |||
ItemSet: require('./lib/timeline/component/ItemSet'), | |||
Legend: require('./lib/timeline/component/Legend'), | |||
LineGraph: require('./lib/timeline/component/LineGraph'), | |||
TimeAxis: require('./lib/timeline/component/TimeAxis') | |||
} | |||
}; | |||
// Network | |||
exports.Network = require('./lib/network/Network'); | |||
exports.network = { | |||
Edge: require('./lib/network/Edge'), | |||
Groups: require('./lib/network/Groups'), | |||
Images: require('./lib/network/Images'), | |||
Node: require('./lib/network/Node'), | |||
Popup: require('./lib/network/Popup'), | |||
dotparser: require('./lib/network/dotparser'), | |||
gephiParser: require('./lib/network/gephiParser') | |||
}; | |||
// Deprecated since v3.0.0 | |||
exports.Graph = function () { | |||
throw new Error('Graph is renamed to Network. Please create a graph as new vis.Network(...)'); | |||
}; | |||
// bundled external libraries | |||
exports.moment = require('./lib/module/moment'); | |||
exports.hammer = require('./lib/module/hammer'); |
@ -0,0 +1,135 @@ | |||
var Point3d = require('./Point3d'); | |||
/** | |||
* @class Camera | |||
* The camera is mounted on a (virtual) camera arm. The camera arm can rotate | |||
* The camera is always looking in the direction of the origin of the arm. | |||
* This way, the camera always rotates around one fixed point, the location | |||
* of the camera arm. | |||
* | |||
* Documentation: | |||
* http://en.wikipedia.org/wiki/3D_projection | |||
*/ | |||
Camera = function () { | |||
this.armLocation = new Point3d(); | |||
this.armRotation = {}; | |||
this.armRotation.horizontal = 0; | |||
this.armRotation.vertical = 0; | |||
this.armLength = 1.7; | |||
this.cameraLocation = new Point3d(); | |||
this.cameraRotation = new Point3d(0.5*Math.PI, 0, 0); | |||
this.calculateCameraOrientation(); | |||
}; | |||
/** | |||
* Set the location (origin) of the arm | |||
* @param {Number} x Normalized value of x | |||
* @param {Number} y Normalized value of y | |||
* @param {Number} z Normalized value of z | |||
*/ | |||
Camera.prototype.setArmLocation = function(x, y, z) { | |||
this.armLocation.x = x; | |||
this.armLocation.y = y; | |||
this.armLocation.z = z; | |||
this.calculateCameraOrientation(); | |||
}; | |||
/** | |||
* Set the rotation of the camera arm | |||
* @param {Number} horizontal The horizontal rotation, between 0 and 2*PI. | |||
* Optional, can be left undefined. | |||
* @param {Number} vertical The vertical rotation, between 0 and 0.5*PI | |||
* if vertical=0.5*PI, the graph is shown from the | |||
* top. Optional, can be left undefined. | |||
*/ | |||
Camera.prototype.setArmRotation = function(horizontal, vertical) { | |||
if (horizontal !== undefined) { | |||
this.armRotation.horizontal = horizontal; | |||
} | |||
if (vertical !== undefined) {< |