git.haldean.org symrep / 90df8db
more solids stuff, better float division Will Haldean Brown 4 years ago
4 changed file(s) with 66 addition(s) and 13 deletion(s). Raw diff Collapse all Expand all
22 from symrep.solids import *
33
44 n = union(
5 sphere(const(1)),
5 difference(
6 intersection(
7 translate(
8 sphere(const(1.0)),
9 vec(-1, 0., 0.),
10 ),
11 translate(
12 box(size(2., 2., 1.75)),
13 vec(-1., 0., 0.25),
14 ),
15 ),
16 translate(
17 cylinder(
18 const(0.35),
19 const(2.0),
20 ),
21 vec(-1., 0., 0.),
22 ),
23 ),
624 intersection(
7 sphere(const(3)),
25 sphere(const(3.)),
826 translate(
9 sphere(const(2)),
27 sphere(const(2.)),
1028 vec(3., 0., 0.),
1129 ),
1230 ),
1331 translate(
1432 difference(
15 sphere(const(2)),
33 sphere(const(2.)),
1634 sphere(const(1.5)),
1735 translate(
18 sphere(const(2)),
36 sphere(const(2.)),
1937 vec(1., 0., 0.),
2038 ),
2139 ),
2745 to_dot(n, f)
2846
2947 points = sample_solid(
30 n, (-2, -2, -2), (5, 5, 2), 20000, is_inside)
31 with open("test.xyz", "w") as f:
48 n, (-2, -2, -2), (5, 5, 2), is_on_surface(0.05), max_sec=30)
49 with open("sphere.xyz", "w") as f:
3250 solids.write_point_cloud(points, f)
0 from __future__ import division
1
02 import array
13 import datetime
24 import math
0 from __future__ import division
1
02 import functools
13 import numpy as np
24 import operator
0 from __future__ import division
1
02 import numpy as np
13 import random
24 import symrep.base
5 import time
36
47
58 def vec(*v):
1518 fill[:3] = p
1619 p = fill
1720 return symrep.base.const(p)
21
22 def size(*s):
23 return symrep.base.const(np.array(s))
1824
1925 def transform(n, T, name=None, nodetype="transform"):
2026 return symrep.base.Node(
4450 name, "sphere",
4551 lambda t: np.linalg.norm(t[:3]) - radius(t), {radius: "radius"})
4652
47 def sample_solid(root, lo, hi, num_points, eval_pt):
53 def cylinder(radius, height, name=None):
54 def eval_t(t):
55 circle_dist = np.linalg.norm(t[:2])
56 axial_dist = abs(t[2])
57 return max(circle_dist - radius(t), axial_dist - height(t) / 2.)
58 return symrep.base.Node(
59 name, "cylinder", eval_t, {radius: "radius", height: "height"})
60
61 def box(size, name=None):
62 return symrep.base.Node(
63 name, "box", lambda t: max(abs(t[:3]) - size(t) / 2.),
64 {size: "size"})
65
66 def sample_solid(root, lo, hi, eval_pt, max_points=None, max_sec=None):
67 if max_points is None and max_sec is None:
68 raise ValueError(
69 "either a deadline or a number of points must be given")
70
4871 found = 0
4972 tried = 0
5073 t = np.ones(4)
51 while found < num_points:
74 start = time.time()
75 while max_points is None or found < max_points:
5276 t[0] = random.uniform(lo[0], hi[0])
5377 t[1] = random.uniform(lo[1], hi[1])
5478 t[2] = random.uniform(lo[2], hi[2])
5680 yield t
5781 found += 1
5882 tried += 1
59 print("tried {} points to find {}".format(tried, num_points))
83 if tried % 1000 == 0:
84 elapsed = time.time() - start
85 if elapsed > max_sec:
86 break
87 print("tried {} points to find {}".format(tried, found))
88 print("estimated scene density: {}".format(found / tried))
6089
6190 def is_inside(root, t):
6291 return root(t) <= 0
6392
64 def is_on_surface(root, t, accuracy):
65 val = root(t)
66 return val <= 0 and abs(val) <= accuracy
93 def is_on_surface(accuracy):
94 def eval_t(root, t):
95 val = root(t)
96 return val <= 0 and abs(val) <= accuracy
97 return eval_t
6798
6899 def write_point_cloud(points, f):
69100 for point in points: