chiark / gitweb /
wip pins
[moebius3.git] / genscad
1 #!/usr/bin/python
2
3 from __future__ import print_function
4
5 import signal
6 signal.signal(signal.SIGINT, signal.SIG_DFL)
7
8 from moebius import *
9
10 nomsize = 20
11 thick = 1.0
12
13 sliceat = 1.675;
14
15 nv = 80
16 nw = 80
17
18 m = Moebius(nv, nw)
19
20
21 class ScadObject:
22   def __init__(so):
23     so._points = []
24     so._point_indices = {}
25     so._triangles = []
26
27   def writeout(so, objname, scalefactor=1):
28     print('module %s(){ scale(%s) polyhedron(points=[' %
29           (objname, scalefactor))
30     for p in so._points: print(p, ',')
31     print('],faces=[')
32     for t in so._triangles: print(repr(t), ',')
33     print('],convexity=10); }')
34     so._points = None
35
36   def _point(so, p):
37     l = list(p)
38     s = repr(l)
39     try:
40       ix = so._point_indices[s]
41     except KeyError:
42       ix = len(so._points)
43       so._points.append(s)
44       so._point_indices[s] = ix
45     return ix
46
47   def triangle(so, a,b,c):
48     ''' a b c  are clockwise from inside '''
49     so._triangles.append([ so._point(p) for p in (a,b,c) ])
50
51   def quad(so, cnrs):
52     ''' cnrs[0] [1] [3] [2] are clockwise from inside '''
53     so.triangle(cnrs[0], cnrs[1], cnrs[3])
54     so.triangle(cnrs[0], cnrs[3], cnrs[2])
55
56   def rquad(so, cnrs):
57     ''' cnrs[0] [1] [3] [2] are anticlockwise from inside '''
58     so.triangle(cnrs[0], cnrs[3], cnrs[1])
59     so.triangle(cnrs[0], cnrs[2], cnrs[3])
60
61 relthick = thick/(nomsize*2)
62
63 def make_moebius(objname):
64   so = ScadObject()
65   for v in range(0, nv):
66     for w in range(0, nw):
67       so.quad([ m.point_offset(v+a, w+b,  relthick)
68                 for a in (0, 1)
69                 for b in (0, 1) ])
70       so.rquad([ m.point_offset(v+a, w+b, -relthick)
71                  for a in (1, 0)
72                  for b in (1, 0) ])
73     for q, w in ((so.quad, 0), (so.rquad, nw)):
74       q([ m.point_offset(v+a, w,  b*relthick)
75           for a in (0, 1)
76           for b in (-1, +1) ])
77   so.writeout(objname, nomsize)
78
79 def make_pinlocations():
80   bests = [ None, None ] # bests[ y>=0 ] = (locn, normal)
81
82   def goodness(info):
83     # we find the one with biggest Z (actually, the least -ve)
84     return (
85       0 * np.linalg.norm(info[0][0:2])
86       -abs(info[1][2])
87     )
88     return abs(info[1][1])
89
90   for v in range(0, nv):
91     for w in range(0, nw):
92       core_quad = [ m.point(v+a, w+b)
93                     for a in (1, 0)
94                     for b in (1, 0) ]
95       for p,q in [ (core_quad[i], core_quad[(i+1) % 4])
96                    for i in range(0,4) ]:
97         normal = (m.point_offset(v,  w,   0.5) - core_quad[0] +
98                   m.point_offset(v+1,w+1, 0.5) - core_quad[3]);
99         if normal[2] > 0: # inwards, make outwards
100           normal = -normal
101
102         #print(repr((p,q)), file=sys.stderr)
103         if (p[2] > -sliceat) == (q[2] > -sliceat): continue
104
105         lincomb = (-sliceat - p[2]) / (q[2] - p[2])
106         here = p * (1-lincomb) + q * lincomb;
107         best_key = here[1] >= 0
108         prospective = (here,normal)
109         if (bests[best_key] is None or
110             goodness(prospective) > goodness(bests[best_key])):
111           bests[best_key] = prospective
112   def print_bests(name, info_index):
113     print('moebius_pin_%s=[' % name)
114     for b in bests: print(repr(list(b[info_index])),',')
115     print('];')
116   print_bests('locns', 0)
117   print_bests('normals', 1)
118
119 make_moebius('MoebiusCore')
120 make_pinlocations()
121 print('moebiuscore_nomsize=%s;' % repr(nomsize))
122 print('moebiuscore_sliceat=%s;' % repr(sliceat))