Skip to content

Commit 671b4f1

Browse files
committed
RenderSystem class in (new) module slvs_solid, two new tests, tests are less verbose (unless you set verbose=True)
1 parent a8dac61 commit 671b4f1

File tree

4 files changed

+189
-167
lines changed

4 files changed

+189
-167
lines changed

solvespace/exposed/slvs_solid.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
from slvs import *
2+
from solid import *
3+
4+
5+
# call to_openscad(), if it exists
6+
def _to_openscad(x):
7+
if hasattr(x, 'to_openscad'):
8+
return x.to_openscad()
9+
elif isinstance(x, list) or isinstance(x, tuple):
10+
return map(_to_openscad, x)
11+
else:
12+
return x
13+
14+
def mat_transpose(m):
15+
for i in range(4):
16+
for j in range(4):
17+
if i < j:
18+
a = m[i][j]
19+
b = m[j][i]
20+
m[i][j] = b
21+
m[j][i] = a
22+
23+
24+
class RenderSystem(object):
25+
__slots__ = "itemscale"
26+
27+
def __init__(self):
28+
self.itemscale = 1
29+
30+
def point3d(self, pt, size = 0.1):
31+
pt = Vector(pt)
32+
size *= self.itemscale
33+
# We want equilateral triangles. I built that in
34+
# in SolveSpace and copied the dimensions.
35+
side = size
36+
hs = side/2
37+
height = size*0.8660
38+
center_to_baseline = size*0.2887
39+
center_to_top = size*0.5773
40+
cb = center_to_baseline
41+
ct = center_to_top
42+
triangle = [ [-hs, -cb], [hs, -cb], [0, ct] ]
43+
pts = [ pt ]
44+
for z in [-height, +height]:
45+
for p in triangle:
46+
pts.append(pt + (p + [z]))
47+
ts = []
48+
for ps in [[0,1,2,3], [0,4,5,6]]:
49+
for a in range(0, 4):
50+
for b in range(a+1, 4):
51+
for c in range(b+1, 4):
52+
ts.append([ps[a], ps[b], ps[c]])
53+
return polyhedron(points = pts,
54+
#triangles = [[1,2,3],[4,6,5]])
55+
triangles = ts)
56+
57+
def line3d(self, a, b, size = 0.01):
58+
a = Vector(a)
59+
b = Vector(b)
60+
length = (b-a).length()
61+
width = size*self.itemscale
62+
wh = width/2
63+
obj = linear_extrude(height = width)(
64+
polygon([ [0,-wh], [0, wh], [length, wh], [length, -wh] ]))
65+
return multmatrix(move_and_rotate(a, b, a+[0,0,1]))(obj)
66+
67+
def system(self, system):
68+
obj = union()
69+
70+
for i in range(system.entities):
71+
t = system.entity_type(i)
72+
if t == SLVS_E_POINT_IN_3D:
73+
obj.add(self.point3d(system.get_Point3d(i)))
74+
elif t == SLVS_E_LINE_SEGMENT:
75+
line = system.get_LineSegment3d(i)
76+
obj.add(self.line3d(line.a(), line.b()))
77+
78+
return obj

solvespace/exposed/test.py

Lines changed: 100 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
from slvs import *
1212
import unittest
1313

14+
verbose = False
15+
1416
def printf(fmt, *args):
1517
print fmt % args
1618

@@ -25,6 +27,9 @@ def floatEqual(self, a, b):
2527
return abs(a-b) < 0.001
2628

2729
def assertFloatEqual(self, a, b):
30+
if not isinstance(a, (int, long, float)) \
31+
or not isinstance(b, (int, long, float)):
32+
self.assertTrue(False, "not a float")
2833
if self.floatEqual(a, b):
2934
self.assertTrue(True)
3035
else:
@@ -35,7 +40,11 @@ def assertFloatListEqual(self, xs, ys):
3540
self.assertListEqual(xs, ys)
3641
else:
3742
for i,a,b in zip(range(len(xs)), xs, ys):
38-
if not self.floatEqual(a, b):
43+
aL = isinstance(a, (list, tuple))
44+
bL = isinstance(b, (list, tuple))
45+
if aL and bL:
46+
self.assertFloatListEqual(a, b)
47+
elif not self.floatEqual(a, b):
3948
self.assertEqual(a, b, "in list at index %d" % i)
4049
self.assertTrue(True)
4150

@@ -100,11 +109,12 @@ def test_example3d(self):
100109
Slvs_Solve(sys, g);
101110

102111
if (sys.result == SLVS_RESULT_OKAY):
103-
print ("okay; now at (%.3f %.3f %.3f)\n" +
104-
" (%.3f %.3f %.3f)") % (
105-
sys.get_param(0).val, sys.get_param(1).val, sys.get_param(2).val,
106-
sys.get_param(3).val, sys.get_param(4).val, sys.get_param(5).val)
107-
print "%d DOF" % sys.dof
112+
if verbose:
113+
print ("okay; now at (%.3f %.3f %.3f)\n" +
114+
" (%.3f %.3f %.3f)") % (
115+
sys.get_param(0).val, sys.get_param(1).val, sys.get_param(2).val,
116+
sys.get_param(3).val, sys.get_param(4).val, sys.get_param(5).val)
117+
print "%d DOF" % sys.dof
108118

109119
self.assertFloatEqual(sys.get_param(0).val, 2.698)
110120
self.assertFloatEqual(sys.get_param(1).val, 2.698)
@@ -208,41 +218,45 @@ def test_example2d(self):
208218
result = sys.solve()
209219

210220
if(result == SLVS_RESULT_OKAY):
211-
printf("solved okay");
212-
printf("line from (%.3f %.3f) to (%.3f %.3f)",
213-
sys.get_param(7).val, sys.get_param(8).val,
214-
sys.get_param(9).val, sys.get_param(10).val);
221+
if verbose:
222+
printf("solved okay");
223+
printf("line from (%.3f %.3f) to (%.3f %.3f)",
224+
sys.get_param(7).val, sys.get_param(8).val,
225+
sys.get_param(9).val, sys.get_param(10).val);
215226
self.assertFloatEqual(sys.get_param( 7).val, 10.000)
216227
self.assertFloatEqual(sys.get_param( 8).val, 11.180)
217228
self.assertFloatEqual(sys.get_param( 9).val, 10.000)
218229
self.assertFloatEqual(sys.get_param(10).val, -18.820)
219230

220-
printf("arc center (%.3f %.3f) start (%.3f %.3f) finish (%.3f %.3f)",
221-
sys.get_param(11).val, sys.get_param(12).val,
222-
sys.get_param(13).val, sys.get_param(14).val,
223-
sys.get_param(15).val, sys.get_param(16).val);
231+
if verbose:
232+
printf("arc center (%.3f %.3f) start (%.3f %.3f) finish (%.3f %.3f)",
233+
sys.get_param(11).val, sys.get_param(12).val,
234+
sys.get_param(13).val, sys.get_param(14).val,
235+
sys.get_param(15).val, sys.get_param(16).val);
224236
self.assertFloatListEqual(
225237
map(lambda i: sys.get_param(i).val, range(11, 17)),
226238
[101.114, 119.042, 116.477, 111.762, 117.409, 114.197])
227239

228-
printf("circle center (%.3f %.3f) radius %.3f",
229-
sys.get_param(17).val, sys.get_param(18).val,
230-
sys.get_param(19).val);
231-
printf("%d DOF", sys.dof);
240+
if verbose:
241+
printf("circle center (%.3f %.3f) radius %.3f",
242+
sys.get_param(17).val, sys.get_param(18).val,
243+
sys.get_param(19).val);
244+
printf("%d DOF", sys.dof);
232245
self.assertFloatEqual(sys.get_param(17).val, 200.000)
233246
self.assertFloatEqual(sys.get_param(18).val, 200.000)
234247
self.assertFloatEqual(sys.get_param(19).val, 17.000)
235248

236249
self.assertEqual(sys.dof, 6)
237250
else:
238-
printf("solve failed: problematic constraints are:");
239-
for i in range(sys.faileds):
240-
printf(" %lu", sys.failed[i]);
241-
printf("");
242-
if (sys.result == SLVS_RESULT_INCONSISTENT):
243-
printf("system inconsistent");
244-
else:
245-
printf("system nonconvergent");
251+
if verbose:
252+
printf("solve failed: problematic constraints are:");
253+
for i in range(sys.faileds):
254+
printf(" %lu", sys.failed[i]);
255+
printf("");
256+
if (sys.result == SLVS_RESULT_INCONSISTENT):
257+
printf("system inconsistent");
258+
else:
259+
printf("system nonconvergent");
246260
self.assertTrue(False, "solve failed")
247261

248262
def test_with_solidpython(self):
@@ -266,5 +280,65 @@ def test_with_solidpython(self):
266280
"\n\npolygon(paths = [[0, 1, 2, 3]], points = [[10.0000000000, 3.0000000000], [17.0000000000, 23.0000000000], [0, 0], [7.0000000000, 2.0000000000, 0.0000000000]]);")
267281

268282

283+
def test_to_openscad(self):
284+
sys = System()
285+
286+
# We want to find the plane for three points. The points
287+
# shouldn't change, so we put them into another group.
288+
289+
p1 = Point3d(1, 1, 9, sys)
290+
p2 = Point3d(5, 2, 2, sys)
291+
p3 = Point3d(0, 7, 5, sys)
292+
293+
# Other entities go into another group
294+
sys.default_group = 2
295+
296+
wrkpl = Workplane(p1, Normal3d(Param(1), Param(0), Param(0), Param(0), sys))
297+
298+
# Some constraints: all points are in the plane
299+
# (p1 is its origin, so we don't need a constraint)
300+
Constraint.on(wrkpl, p2)
301+
Constraint.on(wrkpl, p3)
302+
303+
# Solve it (group 2 is still active)
304+
sys.solve()
305+
306+
self.assertEqual(sys.result, SLVS_RESULT_OKAY)
307+
self.assertFloatListEqual(wrkpl.origin().to_openscad(),
308+
[ 1.000, 1.000, 9.000 ])
309+
self.assertFloatListEqual(wrkpl.normal().vector(),
310+
[ 0.863, -0.261, 0.432, -0.000 ])
311+
self.assertFloatListEqual(wrkpl.to_openscad(),
312+
[[0.6270915888275256, -0.22570772255200192, 0.7455281102701327, 1.0], [-0.22570772255200203, 0.8633874310873447, 0.45124069832139596, 1.0], [-0.7455281102701327, -0.45124069832139607, 0.49047901991447185, 9.0], [0, 0, 0, 1]])
313+
314+
def test_rendersystem_points_and_lines(self):
315+
from slvs_solid import RenderSystem, union, scad_render
316+
317+
r = RenderSystem()
318+
r.itemscale = 4
319+
320+
p1 = [ 2, 0, 0]
321+
p2 = [ 0, 0, 0]
322+
p3 = [ 2, 4, 2]
323+
p4 = [-3, 2, -2]
324+
325+
pts = [ p1, p2, p3, p4 ]
326+
327+
#obj = r.point3d([2, 0, 0]) + r.point3d([0, 0, 0]) + linear_extrude(height = 0.5)(polygon([[0,0,0], [2,0,0], [0,2,0]]))
328+
#obj = union()(map(r.point3d, pts)) + r.line3d(p3, p4)
329+
330+
sys = System()
331+
p1s = Point3d(*(p1 + [sys]))
332+
p2s = Point3d(*(p2 + [sys]))
333+
p3s = Point3d(*(p3 + [sys]))
334+
p4s = Point3d(*(p4 + [sys]))
335+
line = LineSegment3d(p3s, p4s)
336+
337+
obj = r.system(sys)
338+
339+
self.assertEqual(scad_render(obj),
340+
'\n\nunion() {\n\tpolyhedron(points = [[2.0000000000, 0.0000000000, 0.0000000000], [1.8000000000, -0.1154800000, -0.3464000000], [2.2000000000, -0.1154800000, -0.3464000000], [2.0000000000, 0.2309200000, -0.3464000000], [1.8000000000, -0.1154800000, 0.3464000000], [2.2000000000, -0.1154800000, 0.3464000000], [2.0000000000, 0.2309200000, 0.3464000000]], triangles = [[0, 1, 2], [0, 1, 3], [0, 2, 3], [1, 2, 3], [0, 4, 5], [0, 4, 6], [0, 5, 6], [4, 5, 6]]);\n\tpolyhedron(points = [[0.0000000000, 0.0000000000, 0.0000000000], [-0.2000000000, -0.1154800000, -0.3464000000], [0.2000000000, -0.1154800000, -0.3464000000], [0.0000000000, 0.2309200000, -0.3464000000], [-0.2000000000, -0.1154800000, 0.3464000000], [0.2000000000, -0.1154800000, 0.3464000000], [0.0000000000, 0.2309200000, 0.3464000000]], triangles = [[0, 1, 2], [0, 1, 3], [0, 2, 3], [1, 2, 3], [0, 4, 5], [0, 4, 6], [0, 5, 6], [4, 5, 6]]);\n\tpolyhedron(points = [[2.0000000000, 4.0000000000, 2.0000000000], [1.8000000000, 3.8845200000, 1.6536000000], [2.2000000000, 3.8845200000, 1.6536000000], [2.0000000000, 4.2309200000, 1.6536000000], [1.8000000000, 3.8845200000, 2.3464000000], [2.2000000000, 3.8845200000, 2.3464000000], [2.0000000000, 4.2309200000, 2.3464000000]], triangles = [[0, 1, 2], [0, 1, 3], [0, 2, 3], [1, 2, 3], [0, 4, 5], [0, 4, 6], [0, 5, 6], [4, 5, 6]]);\n\tpolyhedron(points = [[-3.0000000000, 2.0000000000, -2.0000000000], [-3.2000000000, 1.8845200000, -2.3464000000], [-2.8000000000, 1.8845200000, -2.3464000000], [-3.0000000000, 2.2309200000, -2.3464000000], [-3.2000000000, 1.8845200000, -1.6536000000], [-2.8000000000, 1.8845200000, -1.6536000000], [-3.0000000000, 2.2309200000, -1.6536000000]], triangles = [[0, 1, 2], [0, 1, 3], [0, 2, 3], [1, 2, 3], [0, 4, 5], [0, 4, 6], [0, 5, 6], [4, 5, 6]]);\n\tmultmatrix(m = [[-0.7453559925, -0.4444444444, -0.2981423970, 2.0000000000], [-0.2981423970, -0.1777777778, 0.7453559925, 4.0000000000], [-0.5962847940, 0.6444444444, 0.0000000000, 2.0000000000], [0, 0, 0, 1]]) {\n\t\tlinear_extrude(height = 0.0400000000) {\n\t\t\tpolygon(paths = [[0, 1, 2, 3]], points = [[0, -0.0200000000], [0, 0.0200000000], [6.7082039325, 0.0200000000], [6.7082039325, -0.0200000000]]);\n\t\t}\n\t}\n}')
341+
342+
269343
if __name__ == '__main__':
270344
unittest.main()

solvespace/exposed/test2.scad.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
print "solved okay"
3333
for p in [p1, p2, p3]:
3434
print "point at (%.3f, %.3f, %.3f)" % tuple(p.to_openscad())
35+
print "normal at (%.3f, %.3f, %.3f, %.3f)" % tuple(wrkpl.normal().vector())
36+
print wrkpl.to_openscad()
3537
print "%d DOF" % sys.dof
3638
else:
3739
print("solve failed")
@@ -76,4 +78,4 @@
7678
plane2 = multmatrix(move_and_rotate(p1, p2, p3))(plane)
7779
geom += plane2
7880

79-
scad_render_to_file(geom, "/tmp/test2.scad")
81+
scad_render_to_file(geom, "/tmp/out.scad")

0 commit comments

Comments
 (0)