diff --git a/abp/server.py b/abp/server.py index 1b8f493..1894176 100644 --- a/abp/server.py +++ b/abp/server.py @@ -7,6 +7,7 @@ import json import threading import time import os +from graph import GraphState class VizHandler(SimpleHTTPRequestHandler): @@ -22,7 +23,7 @@ class VizHandler(SimpleHTTPRequestHandler): self.send_header('Content-Type', 'application/json') self.end_headers() state = self.server.state - self.wfile.write(json.dumps({"state": "{}".format(state)})) + self.wfile.write(state.to_json()) def do_GET(self, *args, **kwargs): """ Someone belled the server """ @@ -62,16 +63,29 @@ class Server(SocketServer.TCPServer): thread.start() print "Server running at http://localhost:{}/".format(self.port) + + +def demograph(): + """ A graph for testing with """ + g = GraphState() + g.add_edge(0, 1) + g.add_edge(1, 2) + g.add_edge(2, 0) + g.add_edge(0, 3) + g.add_edge(100, 200) + return g + + if __name__ == '__main__': - os.chdir(os.path.join(os.path.dirname(__file__), "../static")) - print os.curdir + os.chdir("/home/pete/physics/abp/static") server = Server() server.start() - i = 0 + g = demograph() + + while True: - server.update(i) - i += 1 + server.update(g) time.sleep(1) server.shutdown() diff --git a/static/curve.js b/static/curve.js new file mode 100644 index 0000000..661c4e3 --- /dev/null +++ b/static/curve.js @@ -0,0 +1,24 @@ +// Curve settings +var curveProperties = { + splineDensity: 30, + curvature: 10 +}; + +// Add a curved edge between two points +function makeEdge(e) { + // Make the geometry of the curve + var a = new THREE.Vector3(e.start[0], e.start[1], e.start[2]); + var b = new THREE.Vector3(e.end[0], e.end[1], e.end[2]); + var length = new THREE.Vector3().subVectors(a, b).length(); + var bend = new THREE.Vector3(length / curveProperties.curvature, length / curveProperties.curvature, 0); + var mid = new THREE.Vector3().add(a).add(b).multiplyScalar(0.5).add(bend); + var spline = new THREE.CatmullRomCurve3([a, mid, b]); + var geometry = new THREE.Geometry(); + var splinePoints = spline.getPoints(curveProperties.splineDensity); + Array.prototype.push.apply(geometry.vertices, splinePoints); + + // Make the actual Object3d thing + var line = new THREE.Line(geometry, materials.edge); + return line; +} + diff --git a/static/graph.js b/static/graph.js new file mode 100644 index 0000000..99acec6 --- /dev/null +++ b/static/graph.js @@ -0,0 +1,20 @@ +function buildGraph(json) { + // Add all the qubits + var geometry = new THREE.Geometry(); + var vertex = new THREE.Vector3(0, 0, 0); + geometry.vertices.push(vertex); + var nodes = new THREE.Points(geometry, materials.node); + + // Add all the edges + var edges = new THREE.Object3D(); + edges.add(makeEdge({ + "start": [0, 0, 0], + "end": [1, 1, 1] + })); + + // Construct and return + var graph = new THREE.Object3D(); + graph.add(nodes); + graph.add(edges); + return graph; +} diff --git a/static/grid.js b/static/grid.js new file mode 100644 index 0000000..26412d7 --- /dev/null +++ b/static/grid.js @@ -0,0 +1,23 @@ + +// Make a grid +function makeGrid(side, n, color) { + var markers = new THREE.Object3D(); + var gridStyle = { + color: color, + transparent: true, + linewidth: 1, + opacity: 0.5 + }; + var material = new THREE.LineBasicMaterial(gridStyle); + for (var i = -n / 2; i <= n / 2; ++i) { + var geometry = new THREE.Geometry(); + geometry.vertices.push(new THREE.Vector3(side * i / n, -side / 2, 0)); + geometry.vertices.push(new THREE.Vector3(side * i / n, side / 2, 0)); + var line = new THREE.Line(geometry, material); + var line90 = line.clone(); + line90.rotation.z = Math.PI / 2; + markers.add(line); + markers.add(line90); + } + return markers; +} diff --git a/static/index.html b/static/index.html index 9190527..a847321 100644 --- a/static/index.html +++ b/static/index.html @@ -11,7 +11,10 @@
+ + + diff --git a/static/interaction.js b/static/interaction.js new file mode 100644 index 0000000..e0da09c --- /dev/null +++ b/static/interaction.js @@ -0,0 +1,46 @@ +// Gets a reference to the node nearest to the mouse cursor +function nearestNode() { + raycaster.setFromCamera(mouse, camera); + for (var i = 0; i < nodeGeometry.vertices.length; ++i) { + if (raycaster.ray.distanceSqToPoint(nodeGeometry.vertices[i]) < 0.01) { + return i; + } + } + return undefined; +} + + +// Find out: what is the mouse pointing at? +function checkIntersections() { + var new_selection = nearestNode(); + if (new_selection != selection) { + selection = new_selection; + info.className = selection ? "visible" : "hidden"; + info.innerHTML = selection ? nodeGeometry.labels[new_selection] : info.innerHTML; + render(); + } +} + +// Update the mouse position tracker +function onMouseMove(event) { + mouse.wasClick = false; + mouse.absx = event.clientX; + mouse.absy = event.clientY; + mouse.x = (event.clientX / window.innerWidth) * 2 - 1; + mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; + w = 200; + h = 15; + info.style.top = mouse.absy - h - 40 + "px"; + info.style.left = mouse.absx - w / 2 + "px"; + checkIntersections(); +} + +// Add qubits or whatever +function onClick(event){ + if (!selection){return;} + console.log(nodeGeometry.vertices[selection]); + qubits.geometry.dynamic = true; + qubits.geometry.vertices.push(nodeGeometry.vertices[selection].clone()); + qubits.geometry.verticesNeedUpdate = true; +} + diff --git a/static/main.js b/static/main.js index 8b17aaa..74a7dd7 100644 --- a/static/main.js +++ b/static/main.js @@ -5,174 +5,18 @@ if (typeof console === "undefined") { }; } -var controls, renderer, raycaster, scene, info, nodeGeometry, selection; -var mouse = { - "x": 0, - "y": 0 -}; -var materials = {}; -var curveProperties = { - splineDensity: 30, - curvature: 10 -}; -var camera; -var qubits; +var controls, renderer, raycaster, scene, selection, camera; // Run on startup window.onload = init; -// Add a curved edge between two points -function makeEdge(e) { - // Make the geometry of the curve - var a = new THREE.Vector3(e.start[0], e.start[1], e.start[2]); - var b = new THREE.Vector3(e.end[0], e.end[1], e.end[2]); - var length = new THREE.Vector3().subVectors(a, b).length(); - var bend = new THREE.Vector3(length / curveProperties.curvature, length / curveProperties.curvature, 0); - var mid = new THREE.Vector3().add(a).add(b).multiplyScalar(0.5).add(bend); - var spline = new THREE.CatmullRomCurve3([a, mid, b]); - var geometry = new THREE.Geometry(); - var splinePoints = spline.getPoints(curveProperties.splineDensity); - Array.prototype.push.apply(geometry.vertices, splinePoints); - - // Make the actual Object3d thing - var line = new THREE.Line(geometry, materials.edge); - return line; -} - -function makeQubits() { - qubitGeometry = new THREE.Geometry(); - qubitGeometry.labels = []; - var vertex = new THREE.Vector3(0, 0, 0); - qubitGeometry.vertices.push(vertex); - particles = new THREE.Points(qubitGeometry, materials.qubit); - return particles; -} - // Clear the whole scene function makeScene() { - // Scene, controls, camera and so on var myScene = new THREE.Scene(); - - // Materials - var lineStyle = { - color: "gray", - transparent: false, - linewidth: 1 - }; - materials.edge = new THREE.LineBasicMaterial(lineStyle); - - var pointStyle = { - color: "0xcccccc", - size: 0.1, - map: materials.sprite, - alphaTest: 0.5, - transparent: true, - }; - materials.point = new THREE.PointsMaterial(pointStyle); - - var qubitStyle = { - size: 0.6, - map: materials.sprite, - alphaTest: 0.5, - transparent: true, - color: "red" - }; - materials.qubit = new THREE.PointsMaterial(qubitStyle); - - // Build all the edges - //var edgeGroup = new THREE.Object3D(); - - qubits = makeQubits(); - myScene.add(qubits); - - // Build all the nodes - nodeGeometry = new THREE.Geometry(); - nodeGeometry.labels = []; - for (var i = 0; i < 10; ++i) { - for (var j = 0; j < 10; ++j) { - var vertex = new THREE.Vector3(i - 5, j - 5, 0); - nodeGeometry.vertices.push(vertex); - nodeGeometry.labels.push("Click to add a qubit at (" + i + ", " + j + ")"); - } - } - - var particles = new THREE.Points(nodeGeometry, materials.point); - - var grid = makeGrid(10, 10, "lightgray"); - myScene.add(grid); - - // Add the above stuff into the scene and return - //myScene.add(edgeGroup); - myScene.add(particles); + myScene.add(makeGrid(10, 10, "lightgray")); return myScene; } -// Gets a reference to the node nearest to the mouse cursor -function nearestNode() { - raycaster.setFromCamera(mouse, camera); - for (var i = 0; i < nodeGeometry.vertices.length; ++i) { - if (raycaster.ray.distanceSqToPoint(nodeGeometry.vertices[i]) < 0.01) { - return i; - } - } - return undefined; -} - -// Find out: what is the mouse pointing at? -function checkIntersections() { - var new_selection = nearestNode(); - if (new_selection != selection) { - selection = new_selection; - info.className = selection ? "visible" : "hidden"; - info.innerHTML = selection ? nodeGeometry.labels[new_selection] : info.innerHTML; - render(); - } -} - -// Make a grid -function makeGrid(side, n, color) { - var markers = new THREE.Object3D(); - var gridStyle = { - color: color, - transparent: true, - linewidth: 1, - opacity: 0.5 - }; - var material = new THREE.LineBasicMaterial(gridStyle); - for (var i = -n / 2; i < n / 2; ++i) { - var geometry = new THREE.Geometry(); - geometry.vertices.push(new THREE.Vector3(side * i / n, -side / 2, 0)); - geometry.vertices.push(new THREE.Vector3(side * i / n, side / 2, 0)); - var line = new THREE.Line(geometry, material); - var line90 = line.clone(); - line90.rotation.z = Math.PI / 2; - markers.add(line); - markers.add(line90); - } - return markers; -} - -// Handle mouse movement -function onMouseMove(event) { - mouse.wasClick = false; - mouse.absx = event.clientX; - mouse.absy = event.clientY; - mouse.x = (event.clientX / window.innerWidth) * 2 - 1; - mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; - w = 200; - h = 15; - info.style.top = mouse.absy - h - 40 + "px"; - info.style.left = mouse.absx - w / 2 + "px"; - checkIntersections(); -} - -function onClick(event){ - if (!selection){return;} - console.log(nodeGeometry.vertices[selection]); - qubits.geometry.dynamic = true; - qubits.geometry.vertices.push(nodeGeometry.vertices[selection].clone()); - qubits.geometry.verticesNeedUpdate = true; -} // Render the current frame to the screen function render() { @@ -189,8 +33,6 @@ function loopForever() { // This just organises kickoff function startMainLoop() { scene = makeScene(); - renderer.domElement.addEventListener("mousemove", onMouseMove, false); - renderer.domElement.addEventListener("click", onClick, false); controls.addEventListener("change", render); loopForever(); } @@ -201,23 +43,19 @@ function init() { // Measure things, get references var width = window.innerWidth; var height = window.innerHeight; - info = document.getElementById("infoholder"); - - materials.sprite = new THREE.Texture(document.getElementById("ball")); - materials.sprite.needsUpdate = true; // Renderer - renderer = new THREE.WebGLRenderer({ - antialias: true - }); + renderer = new THREE.WebGLRenderer(); renderer.setSize(width, height); renderer.setClearColor(0xffffff, 1); document.querySelector("body").appendChild(renderer.domElement); + // Time to load the materials + loadMaterials(); + // Camera, controls, raycaster camera = new THREE.PerspectiveCamera(45, width / height, 0.3, 100); controls = new THREE.OrbitControls(camera); - raycaster = new THREE.Raycaster(); // Center the camera controls.center.set(0, 0, 0); diff --git a/static/materials.js b/static/materials.js new file mode 100644 index 0000000..5d1db1d --- /dev/null +++ b/static/materials.js @@ -0,0 +1,34 @@ +var textures = {}; +var materials = {}; + +// Load the site texture from the data URI +function loadMaterials(argument) { + textures.sprite = new THREE.Texture(document.getElementById("ball")); + textures.sprite.needsUpdate = true; + + var lineStyle = { + color: "gray", + transparent: false, + linewidth: 1 + }; + materials.edge = new THREE.LineBasicMaterial(lineStyle); + + var pointStyle = { + color: 0xcccccc, + size: 0.1, + map: textures.sprite, + alphaTest: 0.5, + transparent: true, + }; + materials.point = new THREE.PointsMaterial(pointStyle); + + var qubitStyle = { + size: 0.6, + map: textures.sprite, + alphaTest: 0.5, + transparent: true, + color: "red" + }; + + materials.qubit = new THREE.PointsMaterial(qubitStyle); +} diff --git a/static/poll.js b/static/poll.js index def1d41..b0a337e 100644 --- a/static/poll.js +++ b/static/poll.js @@ -5,12 +5,13 @@ function poll() { var xhr = new XMLHttpRequest(); xhr.onload = function() { - state = JSON.parse(xhr.response); - soft_console.innerHTML = "\n" + xhr.responseText; + state = JSON.parse(xhr.responseText); + console.log(state); + //soft_console.innerHTML = "\n" + xhr.responseText; }; xhr.onerror = function(e){ - soft_console.innerHTML = "\n" + "Lost connection to server"; + //soft_console.innerHTML = "\n" + "Lost connection to server"; }; xhr.open("GET", "/state", true); diff --git a/tests/test_json.py b/tests/test_json.py new file mode 100644 index 0000000..fced196 --- /dev/null +++ b/tests/test_json.py @@ -0,0 +1,26 @@ +from abp.graph import GraphState, DiffedGraphState +from abp import clifford +import time +import json + + +def demograph(): + """ A graph for testing with """ + g = GraphState() + g.add_edge(0, 1) + g.add_edge(1, 2) + g.add_edge(2, 0) + g.add_edge(0, 3) + g.add_edge(100, 200) + return g + + +def test_json_basic(): + """ Test that we can export to JSON """ + g = demograph() + js = g.to_json() + assert "ngbh" in js + assert "vops" in js + json.loads(js) + +