...
 
Commits (6)
FROM python:2.7.18-slim
# Set the working directory to /app
WORKDIR /app
# Copy the current directory contents into the container at /app
ADD . /app
# Install the dependencies
RUN pip install -r requirements.txt
EXPOSE 5001
CMD ["python", "/app/flaskapp/app.py"]
......@@ -9,24 +9,25 @@ from svggen.library import getComponent
from svggen.api.composables.graph.Joint import FingerJoint
'''
known_models = [
wood_models = [
"Stool",
"SimpleTable",
"SimpleChair",
"RockerChair",
"Paperbot",
]
'''
known_models = [
paper_models = [
"BoatBase",
"Tug",
"Canoe",
"Catamaran",
"CatFoil",
"Trimaran",
"Paperbot",
]
known_models = dict([(x, 3) for x in wood_models] + [(x, 0.05) for x in paper_models])
known_types = {
"svg": ("unfolding", "image/svg+xml"),
"dxf": ("silhouette", "application/dxf"),
......@@ -44,6 +45,8 @@ def add_header(response):
def make(f, path, args, mkstl=True, mkdxf=True, mksvg=True):
# Default thickness: paper
t = 0.05
if path in known_models:
t = known_models[path]
for p, v in args.iteritems():
try:
......@@ -113,6 +116,9 @@ def catchall(path):
else:
make(f, component, request.args)
t = known_models.get(component, 0.05)
paperthick = (t == 0.05 and "selected" or "")
woodthick = (t == 3 and "selected" or "")
class ParamForm(Form):
pass
# for k, v in f.getParameterInfo().iteritems():
......@@ -122,12 +128,17 @@ def catchall(path):
setattr(ParamForm, k, MyField("%s: " % k, md, default=v))
if "min" in md and "max" in md and "step" in md:
setattr(ParamForm, k + "_anim", ButtonField("Animate", render_kw={"onclick": "animvar(%s)" % k}))
return render_template("combined.html", component=component, query=request.query_string, form=ParamForm())
return render_template("combined.html",
component=component,
paperthick=paperthick,
woodthick=woodthick,
query=request.query_string,
form=ParamForm())
print component
else:
string = "<html><body>"
for m in known_models:
for (m, t) in known_models.iteritems():
string += '<a href="' + m + '">' + m + "</a><br>"
string += "</body></html>"
return string
......
......@@ -28,8 +28,8 @@
<br><br>
Material:
<select name="$thickness">
<option value="0.05">Paper</option>
<option value="3">3mm plywood</option>
<option value="0.05" {{paperthick}} >Paper</option>
<option value="3" {{woodthick}} >3mm plywood</option>
<option value="5">5mm plywood</option>
</select> <br><br>
......
......@@ -88,6 +88,8 @@ class Graph(Composable, BaseGraph):
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()
'''
......
......@@ -49,6 +49,8 @@ class Drawing:
angle = angles[1][0] - angles[0][0]
if angle == 0:
edge = Flat()
elif e.edgeType is "BEND":
edge = Flex(angle=angle)
else:
edge = Fold(angle=angle)
else:
......
......@@ -241,7 +241,8 @@ class Face(object):
pts2d = np.dot(r, self.pts4d())[0:2,:]
for (i, e) in enumerate(self.edges):
# Follow all non-joints before joints
for (i, e) in sorted(enumerate(self.edges), key=lambda x : x[1].isJoint()):
# XXX hack: don't follow small edges
if e is None or e.isTab():
continue
......@@ -286,6 +287,17 @@ class Face(object):
f.place(e, pcts, tds, facelists, flind)
# end for faces.iteritems
for e in self.edges:
if e.isJoint():
index = self.edgeIndex(e.name)
# print "Jointing ", e.name, "on face", self.name, index
newPts, newEdges = e.joint.go(self, e)
self.pts2d[index:index] = newPts
self.edges[index:index+1] = newEdges
for newEdge in newEdges:
newEdge.join(newEdge.length, self)
e.remove(self)
self.placeagain()
def getTriangleDict(self):
......
......@@ -83,13 +83,13 @@ class Graph():
self.rebuildEdges()
return self
def attachFace(self, fromEdge, newFace, newEdge, prefix=None, angle=0):
def attachFace(self, fromEdge, newFace, newEdge, prefix=None, angle=0, edgeType=None, joints=None):
# XXX should set angle from a face, not absolute angle of the face
self.addFace(newFace, prefix)
if fromEdge is not None:
newEdge = prefixString(prefix, newEdge)
self.mergeEdge(fromEdge, newEdge, angle=angle)
self.mergeEdge(fromEdge, newEdge, angle=angle, edgeType=edgeType, joints=joints)
def delFace(self, facename):
for (i, f) in enumerate(self.faces):
......@@ -140,7 +140,7 @@ class Graph():
def addTab(self, edge1, edge2, angle=0, width=10):
self.mergeEdge(edge1, edge2, angle=angle, tabWidth=width)
def mergeEdge(self, edge1, edge2, angle=0, tabWidth=None, swap=False):
def mergeEdge(self, edge1, edge2, angle=0, tabWidth=None, edgeType=None, joints=None, swap=False):
e1 = self.getEdge(edge1)
e2 = self.getEdge(edge2)
if e1 is None:
......@@ -161,6 +161,11 @@ class Graph():
e2.mergeWith(e1, angle=angle, flip=True, tabWidth=tabWidth)
self.edges.remove(e1)
e2.setType(edgeType)
if joints:
for joint in joints.joints:
e2.addJoint(joint)
return self
def splitEdge(self, edge):
......@@ -181,6 +186,13 @@ class Graph():
self.rebuildEdges()
return new_edges_and_faces
def jointify(self, **kwargs):
for e in self.edges:
if e.isNotFlat() and "joint" in kwargs:
e.setType("JOINT")
e.addJoint(kwargs["joint"])
#print "jointing ", e.name
def tabify(self, tabFace=None, tabDecoration=None, slotFace=None, slotDecoration=None, **kwargs):
for e in self.edges:
if e.isTab():
......
......@@ -3,6 +3,9 @@ from svggen.utils import mymath as np
class HyperEdge:
#ANDYTODO: transform these into sublclasses of HyperEdge and/or componenet
edgeTypes = ["FOLD", "BEND", "JOINT"]
@staticmethod
def edge(allEdges, name, length, face, angle=0, flip=False):
if allEdges is not None:
......@@ -25,6 +28,8 @@ class HyperEdge:
self.tabWidth = None
self.pts2D = None
self.pts3D = None
self.edgeType = "FOLD"
self.joint = None
#self.pt1 = pt1
#self.pt2 = pt2
......@@ -45,11 +50,15 @@ class HyperEdge:
self.name = name
def isNotFlat(self):
return any((x[0] for x in self.faces.values()))
return self.edgeType is "JOINT" or \
(self.edgeType is "FOLD" and any((x[0] for x in self.faces.values())))
def isTab(self):
return self.tabWidth is not None
def isJoint(self):
return self.edgeType is "JOINT" and self.joint is not None
def setAngle(self, face, angle, flip=False):
if face in self.faces:
self.faces[face] = (angle, flip)
......@@ -138,6 +147,20 @@ class HyperEdge:
self.pts2D = pts2D
self.pts3D = pts3D
def setType(self, edgeType):
if edgeType is None:
return # do nothing
if edgeType not in self.edgeTypes:
raise Exception("Invalid edge type!")
self.edgeType = edgeType
def addJoint(self, joint):
if not self.edgeType is "JOINT":
raise Exception("Trying to add joints to a non-joint edge")
# if not isinstance(joint, Joint.Joint):
# raise Exception("Not a joint!")
self.joint = joint
def __eq__(self, other):
return self.name == other.name
......
from svggen.api.composables.graph.HyperEdge import HyperEdge
import svggen.utils.mymath as np
class Joint:
def __init__(self, **kwargs):
self.kwargs = kwargs
def go(face, edge):
pass
class FingerJoint(Joint):
def go(self, face, edge):
inset = False
edgename = face.name + edge.name
index = face.edgeIndex(edge.name)
angle, flip = edge.faces[face]
thickness = self.kwargs["thickness"]
coords = face.edgeCoords(index)
length = face.edgeLength(index)
if inset:
length -= thickness
pt1 = np.array(coords[0])
pt2 = np.array(coords[1])
n = int(max(3, round(length * 1.0 / thickness))) # number of fingers
dt = length * 1.0 / n # actual thickness of fingers
dlp = thickness / 2.
dln = thickness / 2. # Only works for 90deg angles; np.sqrt(2) max
dl = dlp + dln # actual length of fingers
flip = flip and (n % 2 == 1)
dpt = (pt2 - pt1) * 1.0 * dt / face.edgeLength(index)
ppt = np.array((dpt[1], -dpt[0])) / dt
newEdges = []
newPts = []
newPt = coords[0]
def addNew(newEdge, newPt):
newEdges.append(newEdge)
newPts.append(newPt)
newEdge.join(newEdge.length, face)
if inset:
# inset from the edge for 3 face corners
newPt = newPt - ppt * dln
newEdge = HyperEdge(edgename + "fjx1", dln)
addNew(newEdge, newPt)
newPt = newPt + dpt * thickness / dt / 2.0
newEdge = HyperEdge(edgename + "fjx2", dt)
addNew(newEdge, newPt)
newPt = newPt + ppt * dln
newEdge = HyperEdge(edgename + "fjx3", dln)
addNew(newEdge, newPt)
if flip:
newPt = newPt + ppt * dlp
newEdge = HyperEdge(edgename + "fj0", dlp)
else:
newPt = newPt - ppt * dln
newEdge = HyperEdge(edgename + "fj0", dln)
for i in range(int(n)):
addNew(newEdge, newPt)
newPt = newPt + dpt
newEdge = HyperEdge(edgename + "fjd%d" % i, dt)
addNew(newEdge, newPt)
if flip:
newPt = newPt - ppt * dl
else:
newPt = newPt + ppt * dl
newEdge = HyperEdge(edgename + "fjp%d" % i, dl)
flip = not flip
if not flip:
addNew(newEdge, newPt)
else:
newPt = newPt - ppt * dl
if inset:
newPt = newPt + dpt * thickness / dt / 2.0
newEdge = HyperEdge(edgename + "fjy", dt)
addNew(newEdge, newPt)
newEdge = HyperEdge(edgename + "fjn", dln)
newEdges.append(newEdge)
return newPts, newEdges