...
 
Commits (9)
......@@ -47,7 +47,7 @@ def make(f, path, args, mkstl=True, mkdxf=True, mksvg=True):
if p == '$thickness' or p == '%24thickness':
t = float(v)
except ValueError as e:
print repr(e)
print "*** ERROR ***", repr(e)
pass
j = None
......@@ -56,16 +56,16 @@ def make(f, path, args, mkstl=True, mkdxf=True, mksvg=True):
try:
print join(app.static_folder, path)
ss = f.makeOutput(join(app.static_folder, path),
tree=False, unfolding=mksvg, animate=False,
autofolding=False, display=False,
silhouette=mkdxf, stl=mkstl, stlstr=True,
f.makeOutput(join(app.static_folder, path), default=False,
unfolding=mksvg, silhouette=mkdxf, stl=mkstl,
thickness = t, joint = j)
ss = f.makeOutput(None, remake=False, default=False,
unfolding=mksvg, silhouette=mkdxf, stl=mkstl,
thickness = t, joint = j)
stlstr = ss["graph"]["stl"]
except Exception as e:
print repr(e)
print "*** ERROR ***", repr(e)
return repr(e)
return stlstr
return ss["graph"]
@app.route('/', defaults={'path': ''}, methods=['GET', 'POST'])
@app.route('/<path:path>', methods=['GET', 'POST'])
......@@ -75,7 +75,7 @@ def catchall(path):
try:
path, ext = path.split('.')
except ValueError as e:
print repr(e)
print "*** ERROR ***", repr(e)
abort(400)
component = path
......@@ -84,22 +84,19 @@ def catchall(path):
try:
f = getComponent(component)
except Exception as e:
print repr(e)
print "*** ERROR ***", repr(e)
abort(404)
if ext == "json":
return jsonify(f.getParameterInfo())
elif ext == "ajax":
ss = make(f, component, request.form)
return "Good"
return jsonify(ss)
elif ext == "svg":
#make(f, component, request.args, mkstl=False, mkdxf=False, mksvg=True)
return send_from_directory(join(app.static_folder, component), "graph-print.svg", as_attachment=True, cache_timeout=-1)
elif ext == "stl":
#make(f, component, request.args, mkstl=True, mkdxf=False, mksvg=False)
return send_from_directory(join(app.static_folder, component), "graph-model.stl", as_attachment=True, cache_timeout=-1)
elif ext == "dxf":
#make(f, component, request.args, mkstl=False, mkdxf=True, mksvg=False)
return send_from_directory(join(app.static_folder, component), "graph-silhouette.dxf", as_attachment=True, cache_timeout=-1)
elif ext:
abort(400)
......
......@@ -47,8 +47,6 @@ function stlinit() {
controls.enableKeys = false;
container.appendChild(renderer.domElement);
stlload();
}
function addShadowedLight( x, y, z, color, intensity ) {
......@@ -69,34 +67,32 @@ function addShadowedLight( x, y, z, color, intensity ) {
}
var mesh;
function stlload() {
var material = new THREE.MeshPhongMaterial( { color: 0xff5533, specular: 0x111111, shininess: 200 } );
function stlload(stlmodel) {
// OBJECT
var loader = new THREE.STLLoader();
if (typeof stlmodel == "undefined")
stlmodel = 'static/graph-model.stl';
loader.load( stlmodel, function ( geometry ) {
geometry = loader.parse( stlmodel );
var material = new THREE.MeshPhongMaterial( { color: 0xff5533, specular: 0x111111, shininess: 200 } );
mesh = new THREE.Mesh( geometry, material );
mesh.castShadow = true;
mesh.receiveShadow = true;
mesh.scale.set(1000, 1000, 1000);
mesh = new THREE.Mesh( geometry, material );
mesh.castShadow = true;
mesh.receiveShadow = true;
mesh.scale.set(1000, 1000, 1000);
geometry.computeFaceNormals();
geometry.computeVertexNormals();
geometry.computeFaceNormals();
geometry.computeVertexNormals();
scene.add( mesh );
} );
scene.add( mesh );
}
function stlunload() {
scene.remove(mesh);
}
function stlreload() {
function stlreload(stlmodel) {
stlunload();
stlload();
stlload(stlmodel);
render();
}
......@@ -111,17 +107,26 @@ paramform.addEventListener("submit", function (event) {
event.preventDefault();
remake();
});
paramform.addEventListener("onchange", function (event) {
remake();
});
function svgreload(svgmodel) {
swapSVG(document.getElementById('dxf'), svgmodel);
}
function remake() {
var xhr = new XMLHttpRequest();
var formdata = new FormData(paramform);
console.log(new URLSearchParams(formdata).toString())
// Define what happens on successful data submission
xhr.addEventListener("load", function(event) {
console.log('success: ');
console.log(event.target.responseText);
stlreload();
svgreload();
data = JSON.parse(event.target.responseText);
console.log(Object.keys(data))
stlreload(data["stl"]);
svgreload(data["unfolding"]);
});
// Define what happens in case of error
......
var zoomScale = 0.2; // Zoom sensitivity
var svg;
// Create an SVG point that contains x & y values
var point;
// We save the original values from the viewBox
var viewBox;
function swapSVG(par, svgstring) {
par.innerHTML = svgstring;
svg = document.querySelector('svg');
svg.setAttribute("height", "100%");
svg.setAttribute("width", "100%");
if (viewBox) {
svg.viewBox.baseVal.x = viewBox.x;
svg.viewBox.baseVal.y = viewBox.y;
svg.viewBox.baseVal.width = viewBox.width;
svg.viewBox.baseVal.height = viewBox.height;
}
setupHandlers();
}
function setupHandlers() {
// We select the SVG into the page
svg = document.querySelector('svg');
// If browser supports pointer events
if (window.PointerEvent) {
svg.addEventListener('pointerdown', onPointerDown); // Pointer is pressed
svg.addEventListener('pointerup', onPointerUp); // Releasing the pointer
svg.addEventListener('pointerleave', onPointerUp); // Pointer gets out of the SVG area
svg.addEventListener('pointermove', onPointerMove); // Pointer is moving
} else {
// Add all mouse events listeners fallback
svg.addEventListener('mousedown', onPointerDown); // Pressing the mouse
svg.addEventListener('mouseup', onPointerUp); // Releasing the mouse
svg.addEventListener('mouseleave', onPointerUp); // Mouse gets out of the SVG area
svg.addEventListener('mousemove', onPointerMove); // Mouse is moving
// Add all touch events listeners fallback
svg.addEventListener('touchstart', onPointerDown); // Finger is touching the screen
svg.addEventListener('touchend', onPointerUp); // Finger is no longer touching the screen
svg.addEventListener('touchmove', onPointerMove); // Finger is moving
}
if(navigator.userAgent.toLowerCase().indexOf('webkit') >= 0)
window.addEventListener('mousewheel', handleMouseWheel, false); // Chrome/Safari
else
window.addEventListener('DOMMouseScroll', handleMouseWheel, false); // Others
// Create an SVG point that contains x & y values
point = svg.createSVGPoint();
// We save the original values from the viewBox
viewBox = svg.viewBox.baseVal;
}
// This function returns an object with X & Y values from the pointer event
function getPointFromEvent (event) {
// If even is triggered by a touch event, we get the position of the first finger
if (event.targetTouches) {
point.x = event.targetTouches[0].clientX;
point.y = event.targetTouches[0].clientY;
} else {
point.x = event.clientX;
point.y = event.clientY;
}
// We get the current transformation matrix of the SVG and we inverse it
var invertedSVGMatrix = svg.getScreenCTM().inverse();
return point.matrixTransform(invertedSVGMatrix);
}
// This variable will be used later for move events to check if pointer is down or not
var isPointerDown = false;
// This variable will contain the original coordinates when the user start pressing the mouse or touching the screen
var pointerOrigin;
// Function called by the event listeners when user start pressing/touching
function onPointerDown(event) {
isPointerDown = true; // We set the pointer as down
// We get the pointer position on click/touchdown so we can get the value once the user starts to drag
pointerOrigin = getPointFromEvent(event);
}
// Function called by the event listeners when user start moving/dragging
function onPointerMove (event) {
// Only run this function if the pointer is down
if (!isPointerDown) {
return;
}
// This prevent user to do a selection on the page
event.preventDefault();
// Get the pointer position as an SVG Point
var pointerPosition = getPointFromEvent(event);
// Update the viewBox variable with the distance from origin and current position
// We don't need to take care of a ratio because this is handled in the getPointFromEvent function
viewBox.x -= (pointerPosition.x - pointerOrigin.x);
viewBox.y -= (pointerPosition.y - pointerOrigin.y);
}
function onPointerUp() {
// The pointer is no longer considered as down
isPointerDown = false;
}
/**
* Handle mouse wheel event.
*/
function handleMouseWheel(evt) {
if(evt.preventDefault)
evt.preventDefault();
evt.returnValue = false;
// Chrome/Safari : Mozilla
var delta = evt.wheelDelta ? evt.wheelDelta / -360 : evt.detail / 9;
var z = Math.pow(1 + zoomScale, delta);
var pointerPosition = getPointFromEvent(evt);
viewBox.x += pointerPosition.x;
viewBox.y += pointerPosition.y;
viewBox.height *= z;
viewBox.width *= z;
var newPointerPosition = getPointFromEvent(evt);
viewBox.x -= (newPointerPosition.x - pointerPosition.x);
viewBox.y -= (newPointerPosition.y - pointerPosition.y);
}
......@@ -39,11 +39,13 @@
height: 70vh;
}
#dxf {
background: aliceblue;
position: fixed;
bottom: 0;
right: 0;
width: 80vw;
height: 30vh;
padding: 5px;
}
</style>
......@@ -78,16 +80,9 @@
</div>
<div id="stl"></div>
<div id="dxf">
<img id="svg" src="{{ component }}.svg">
</div>
<div id="dxf"></div>
<script>stlmodel = 'static/{{ component }}/graph-model.stl'</script>
<script>
function svgreload() {
document.getElementById('svg').src = "{{ component }}.svg?random="+new Date().getTime();
}
</script>
<script src="static/svgpan.js"></script>
<script src="static/my.js"></script>
</body>
......
......@@ -465,11 +465,11 @@ class Component(Parameterized):
for key, val in self._test_params.iteritems():
self.setParameter(key, val)
print "Compiling robot designs to directory", filedir, '...'
sys.stdout.flush()
if kw("remake", True):
print "Compiling robot designs to directory", filedir, '...'
sys.stdout.flush()
self.make()
print "done."
print "done."
# XXX: Is this the right way to do it?
import os
......
from graph.Graph import Graph as BaseGraph
from Composable import Composable
from svggen.utils.utils import tryImport, decorateGraph
from StringIO import StringIO
class Decoration(Composable, BaseGraph):
......@@ -69,9 +70,12 @@ class Graph(Composable, BaseGraph):
def makeOutput(self, filedir, **kwargs):
import sys
if "displayOnly" in kwargs:
kwDefault = not kwargs["displayOnly"]
kwargs["display"] = kwargs["displayOnly"]
elif "default" in kwargs:
kwDefault = kwargs["default"]
else:
kwDefault = True
......@@ -80,12 +84,13 @@ class Graph(Composable, BaseGraph):
return kwargs[arg]
return default
from svggen.utils.tabs import BeamTabs, BeamTabDecoration, BeamSlotDecoration
self.tabify(kw("tabFace", BeamTabs), kw("tabDecoration", BeamTabDecoration),
kw("slotFace", None), kw("slotDecoration", BeamSlotDecoration))
if kw("joint", None):
self.jointify(**kwargs)
self.place()
if kw("remake", True):
from svggen.utils.tabs import BeamTabs, BeamTabDecoration, BeamSlotDecoration
self.tabify(kw("tabFace", BeamTabs), kw("tabDecoration", BeamTabDecoration),
kw("slotFace", None), kw("slotDecoration", BeamSlotDecoration))
if kw("joint", None):
self.jointify(**kwargs)
self.place()
'''
print
......@@ -106,54 +111,32 @@ class Graph(Composable, BaseGraph):
from svggen.utils.display import displayTkinter
displayTkinter(d)
basename = filedir + "/" + kw("name", "") + "-"
basename = None
if filedir:
basename = filedir + "/" + kw("name", "") + "-"
rets = {}
if kw("unfolding"):
print "Generating cut-and-fold pattern... ",
sys.stdout.flush()
d.toSVG(basename + "lasercutter.svg", mode="Corel")
print "done."
if kw("unfolding"):
print "Generating printer pattern... ",
sys.stdout.flush()
d.toSVG(basename + "print.svg", mode="print")
print "done."
if kw("animate"):
print "Generating OrigamiSimulator pattern... ",
sys.stdout.flush()
d.toSVG(basename + "anim.svg", mode="animate")
print "done."
if kw("silhouette"):
print "Generating cut-and-fold pattern for Silhouette papercutter... ",
sys.stdout.flush()
d.toDXF(basename + "silhouette.dxf", mode="silhouette")
print "done."
if kw("autofolding"):
print "Generating autofolding pattern... ",
sys.stdout.flush()
d.toDXF(basename + "autofold-default.dxf", mode="autofold")
print "(graph) ... ",
sys.stdout.flush()
self.toDXF(basename + "autofold-graph.dxf")
print "done."
if kw("stl"):
print "Generating 3D model... ",
sys.stdout.flush()
self.toSTL(basename + "model.stl", **kwargs)
print "done."
if kw("stlstr"):
print "Generating 3D model (string)... ",
sys.stdout.flush()
s = self.toSTL(None, **kwargs)
rets["stl"] = s
print "done."
def handle(keyword, text, fn, stub, **ka):
if kw(keyword):
print "Generating %s pattern... " % text,
sys.stdout.flush()
if basename:
with open(basename+stub, 'w') as fp:
fn(fp, **ka)
else:
buf = StringIO()
fn(buf, **ka)
rets[keyword] = buf.getvalue()
print "done."
handle("unfolding", "Corel cut-and-fold", d.toSVG, "lasercutter.svg", mode="Corel")
handle("unfolding", "printer", d.toSVG, "lasercutter.svg", mode="print")
handle("animate", "OrigamiSimulator", d.toSVG, "anim.svg", mode="animate")
handle("silhouette", "Silhouette cut-and-fold", d.toDXF, "silhouette.dxf", mode="silhouette")
handle("autofolding", "autofolding", d.toDXF, "autofold-default.dxf", mode="autofold")
handle("autofolding", " -- (graph)", d.toDXF, "autofold-graph.dxf")
handle("stl", "3D", self.toSTL, "model.stl", **kwargs)
return rets
......@@ -62,18 +62,18 @@ class Drawing:
for e in face.get2DDecorations():
self.edges[e[0]] = Edge(e[0], e[1] + [dx, dy], e[2] + [dx, dy], EdgeType(e[3], interior=True))
def toDXF(self, filename, labels=False, mode="dxf"):
def toDXF(self, fp, labels=False, mode="dxf"):
from dxfwrite import DXFEngine as dxf
'''
if mode == "silhouette":
self.append(Rectangle(12*25.4, 12*25.4, edgetype=Reg()), "outline")
'''
dwg = dxf.drawing(filename)
dwg = dxf.drawing()
EdgeType.makeLinetypes(dwg, dxf)
for e in self.edges.items():
e[1].toDrawing(dwg, e[0] if labels else "", mode=mode, engine=dxf)
dwg.save()
dwg.save_to_fileobj(fp)
'''
if mode == "silhouette":
......@@ -83,7 +83,7 @@ class Drawing:
self.edges.pop("outline.e3")
'''
def toSVG(self, filename, labels=False, mode=None):
def toSVG(self, fp, labels=False, mode=None):
"""
Writes all Edge instances to a SVG file.
......@@ -100,12 +100,12 @@ class Drawing:
dx = maxx-minx
dy = maxy-miny
svg = svgwrite.Drawing(filename,
svg = svgwrite.Drawing(None,
size=('%fmm' % dx, '%fmm' % dy),
viewBox=('%f %f %f %f' % (minx, miny, dx, dy)))
for e in self.edges.items():
e[1].toDrawing(svg, e[0] if labels else "", mode)
svg.save()
svg.write(fp, pretty=True)
def points(self):
"""
......
......@@ -19,10 +19,10 @@ def inflate(face, thickness=.1, edges=False):
return faces
def STLWrite(faces, filename, **kwargs):
def STLWrite(faces, fp, **kwargs):
scale = .001 # roco units : mm ; STL units m
from stlwriter import Binary_STL_Writer
from stlwriter import ASCII_STL_Writer as STL_Writer
import triangle
shells = []
......@@ -48,41 +48,24 @@ def STLWrite(faces, filename, **kwargs):
facets.append(np.dot(r, t) * scale)
triangles.extend(facets)
'''
# Output each face to its own STL file
if filename:
with open(filename.replace(".stl", "_%02d.stl" % i), 'wb') as fp:
writer = Binary_STL_Writer(fp)
writer = STL_Writer(fp)
writer.add_faces(facets)
writer.close()
'''
faces = triangles
if filename:
with open(filename, 'wb') as fp:
writer = Binary_STL_Writer(fp)
writer.add_faces(faces)
writer.close()
else:
import StringIO
buf = StringIO.StringIO()
writer = Binary_STL_Writer(buf)
writer.add_faces(faces)
writer.close()
return buf.getvalue()
def DXFWrite(edges, filename):
from dxfwrite import DXFEngine as dxf
dwg = dxf.drawing(filename)
for e in edges:
if e[2] is None:
kwargs = {"layer": "Cut"}
else:
kwargs = {"layer": repr(e[2])}
dwg.add(dxf.line((e[0][0], e[0][1]), (e[1][0], e[1][1]), **kwargs))
dwg.save()
writer = STL_Writer(fp)
writer.add_faces(faces)
writer.close()
class Graph():
def __init__(self):
self.faces = []
self.facelists = []
self.edges = []
def addFace(self, f, prefix=None, faceEdges=None, faceAngles=None, faceFlips=None):
......@@ -274,9 +257,9 @@ class Graph():
def place(self, force=False):
if force:
self.unplace()
self.facelists = []
transform3D = np.eye(4)
self.facelists = []
while True:
for f in self.faces:
......@@ -301,7 +284,7 @@ class Graph():
f.pts2D = None
f.pts3D = None
def toSTL(self, filename, **kwargs):
def toSTL(self, fp, **kwargs):
self.place()
stlFaces = []
for face in self.faces:
......@@ -311,18 +294,7 @@ class Graph():
else:
print "skipping face:", face.name
'''
return STLWrite(stlFaces, filename, **kwargs)
def toSVG(self, filename):
# XXX TODO
self.place()
dxfEdges = [list(e.pts2D) + [e.getInteriorAngle()] for e in self.edges if e.pts2D is not None]
DXFWrite(dxfEdges, filename)
def toDXF(self, filename):
self.place()
dxfEdges = [list(e.pts2D) + [e.getInteriorAngle()] for e in self.edges if e.pts2D is not None]
DXFWrite(dxfEdges, filename)
return STLWrite(stlFaces, fp, **kwargs)
'''
@staticmethod
......