def antiprism_model(pgon, arg_type): """Construct antiprism model with golden trapziums""" N = pgon.N ang = pgon.angle() / 2 P = tri_antiprism_pt(pgon, gold_trap_diag, 1, phi) Q = Vec(P[0], -P[1], -P[2]) points = [] for i in range(N): points.append(P.rot_z(2 * i * ang)) for i in range(N): points.append(Q.rot_z(2 * i * ang)) R = points[N - 1] + (P - Q) * phi for i in range(N): points.append(R.rot_z(2 * i * ang)) S = Vec(R[0], -R[1], -R[2]) for i in range(N): points.append(S.rot_z(2 * i * ang)) faces = [] faces.append([2 * N + i for i in range(N)]) faces.append([3 * N + i for i in range(N)]) for i in range(N): faces.append([i, 2 * N + i, 2 * N + ((i + 1) % N)]) faces.append([N + i, 3 * N + i, 3 * N + ((i - 1) % N)]) faces.append( [i, 2 * N + ((i + 1) % N), ((i + 1) % N), N + ((i + 1) % N)]) faces.append([i, N + ((i + 1) % N), 3 * N + i, N + i]) return points, faces
def get_base_points(pgon, centres=0, twist=False): N = pgon.N D = pgon.D a = pgon.angle()/2 points = [Vec(0, 0, 1), Vec(0, 0, -1)] # poles A = a B = math.pi/2 * (1 - D/N) cos_lat = 1/(math.tan(A) * math.tan(B)) sin_lat = math.sqrt(1 - cos_lat**2) p_north = Vec(sin_lat, 0, cos_lat) p_south = Vec(sin_lat, 0, -cos_lat) for i in range(N): points.append(p_north.rot_z(i*2*a)) for i in range(N): points.append(p_south.rot_z(i*2*a+a)) if centres: cos_cent_lat = math.cos(B)/math.sin(A) sin_cent_lat = math.sqrt(1 - cos_cent_lat**2) cent_north = Vec(sin_cent_lat, 0, cos_cent_lat) cent_south = Vec(sin_cent_lat, 0, -cos_cent_lat) for i in range(N): points.append(cent_north.rot_z(i*2*a+a) * centres) for i in range(N): points.append(cent_south.rot_z(i*2*a) * centres) rhombi = [] for i in range(N): rhombi.append([2 + i, 0, 2 + ((i+1) % N), 2 + N + i]) for i in range(N): rhombi.append([2 + N + i, 1, 2 + N + ((i-1) % N), 2 + i]) if twist: hx = [0, 2, 2 + N, 1, 2 + N+N//2, 2 + N-N//2] axis = points[hx[0]] + points[hx[2]] + points[hx[4]] rot = Mat.rot_axis_ang(axis.unit(), 2*math.pi/3) for i in list(range(hx[5]+1, 2 + N)) + list(range(hx[4]+1, 2 + 2*N)): points[i] = rot * points[i] if centres: for r in list(range(N-N//2, N+1)) + list(range(2*N-N//2, 2*N)): points[2 + 2*N + r] = rot * points[2 + 2*N + r] for r in list(range(N-N//2, N+1)) + list(range(2*N-N//2, 2*N)): for i in range(4): for idx, p_idx in enumerate(hx): if p_idx == rhombi[r][i]: rhombi[r][i] = hx[(idx+2) % 6] break return points, rhombi
def j89_get_principal_verts(pgon, ang, flags): bad = flags.strip('ABC') if bad: raise ValueError('Unrecognised form flag(s) \''+bad+'\'') ridge_down = 'A' in flags ridge2_down = 'B' in flags belt_back = 'C' in flags pgon.N *= 2 # p_ang2 = pgon2.angle() A, B, B2, C = get_pstt_cap_verts(pgon, ang, ridge_down) pgon.N //= 2 p_ang = pgon.angle()/2 A2_rad = pgon.circumradius(edge) # circumradius of top polygon sq_mid = (B + B2) / 2 sq_mid_rad = Vec(sq_mid[0], sq_mid[1], 0).mag() tri_ht2 = 3/4 - (A2_rad - sq_mid_rad)**2 if tri_ht2 < -epsilon: raise ValueError( 'Not possible to calculate upper equilateral triangle') A2_ht = (1 - 2*belt_back)*sqrt(tri_ht2) + B[2] A2 = Vec(A2_rad, 0, A2_ht).rot_z(p_ang/2) A2_minus1 = A2.rot_z(-2*p_ang) B2_minus1 = B2.rot_z(-2*p_ang) C2 = get_three_line_vert(A2_minus1, A2, B2_minus1, B, ridge2_down) return [pt.rot_z(p_ang/2) for pt in [A, B, B2, C, A2, C2]]
def make_frame(frame_elems, pgon, axis_angle, num_segs): points = [] faces = [] if frame_elems: v0 = Vec(0, 0, 1) v1 = Vec(-math.sin(axis_angle), 0, math.cos(axis_angle)) v2 = v1.rot_z(pgon.angle() / 2) v2[2] *= -1 if 'r' in frame_elems: ps, fs = make_arc(v0, v1, num_segs, 0) points += ps faces += fs ps, fs = make_arc(v1, v2, num_segs, num_segs + 1) points += ps faces += fs if 'a' in frame_elems: faces += [[len(points) + i, len(points) + i + 1] for i in range(0, 6, 2)] points += [v0, -v0, v1, -v1, v2, -v2] rad = calc_polygons(pgon, 0, axis_angle, -1)[0][0].mag() points = [rad * p for p in points] faces += [[i] for i in range(len(points))] return points, faces
def j89_get_principal_verts(pgon, ang, flags): bad = flags.strip('ABC') if bad: raise ValueError('Unrecognised form flag(s) \'' + bad + '\'') ridge_down = 'A' in flags ridge2_down = 'B' in flags belt_back = 'C' in flags pgon.N *= 2 # p_ang2 = pgon2.angle() A, B, B2, C = get_pstt_cap_verts(pgon, ang, ridge_down) pgon.N //= 2 p_ang = pgon.angle() / 2 A2_rad = pgon.circumradius(edge) # circumradius of top polygon sq_mid = (B + B2) / 2 sq_mid_rad = Vec(sq_mid[0], sq_mid[1], 0).mag() tri_ht2 = 3 / 4 - (A2_rad - sq_mid_rad)**2 if tri_ht2 < -epsilon: raise ValueError( 'Not possible to calculate upper equilateral triangle') A2_ht = (1 - 2 * belt_back) * sqrt(tri_ht2) + B[2] A2 = Vec(A2_rad, 0, A2_ht).rot_z(p_ang / 2) A2_minus1 = A2.rot_z(-2 * p_ang) B2_minus1 = B2.rot_z(-2 * p_ang) C2 = get_three_line_vert(A2_minus1, A2, B2_minus1, B, ridge2_down) return [pt.rot_z(p_ang / 2) for pt in [A, B, B2, C, A2, C2]]
def get_pstt_cap_verts(pgon, ang, ridge_down): p_ang = pgon.angle() / 2 rad = pgon.circumradius(edge) # Polygon vertex A = Vec(rad, 0, 0) # First and last square vertices B = Vec(rad + edge * cos(ang) * cos(p_ang), edge * cos(ang) * sin(p_ang), edge * sin(ang)) B2 = Vec(B[0], -B[1], B[2]).rot_z(2 * p_ang) A_minus1 = A.rot_z(-2 * p_ang) B2_minus1 = B2.rot_z(-4 * p_ang) C = get_three_line_vert(A, A_minus1, B, B2_minus1, ridge_down) return A, B, B2, C
def get_pstt_cap_verts(pgon, ang, ridge_down): p_ang = pgon.angle()/2 rad = pgon.circumradius(edge) # Polygon vertex A = Vec(rad, 0, 0) # First and last square vertices B = Vec(rad + edge*cos(ang)*cos(p_ang), edge*cos(ang)*sin(p_ang), edge*sin(ang)) B2 = Vec(B[0], -B[1], B[2]).rot_z(2*p_ang) A_minus1 = A.rot_z(-2*p_ang) B2_minus1 = B2.rot_z(-4*p_ang) C = get_three_line_vert(A, A_minus1, B, B2_minus1, ridge_down) return A, B, B2, C
def make_frame(frame_elems, pgon, axis_angle, num_segs): points = [] faces = [] if frame_elems: v0 = Vec(0, 0, 1) v1 = Vec(-math.sin(axis_angle), 0, math.cos(axis_angle)) v2 = v1.rot_z(pgon.angle()/2) v2[2] *= -1 if 'r' in frame_elems: ps, fs = make_arc(v0, v1, num_segs, 0) points += ps faces += fs ps, fs = make_arc(v1, v2, num_segs, num_segs+1) points += ps faces += fs if 'a' in frame_elems: faces += [[len(points)+i, len(points)+i+1] for i in range(0, 6, 2)] points += [v0, -v0, v1, -v1, v2, -v2] rad = calc_polygons(pgon, 0, axis_angle, -1)[0][0].mag() points = [rad * p for p in points] faces += [[i] for i in range(len(points))] return points, faces
def make_ring(R, N, a): b = ring_ball_ang(N, a) P = Vec(R * math.sin(a - b), 0, R * math.cos(a - b)) return [P.rot_z(2 * math.pi * i / N) for i in range(N)], b
def cup_model(pgon, model_type): """Construct cupula model with golden trapziums""" ang = pgon.angle() / 2 if model_type in ['0']: len_a, len_b, len_c = (phi - 1) / sin(math.pi / 2 - ang), 1, phi elif model_type in ['1', '2']: len_a, len_b, len_c = phi, 1, phi elif model_type in ['3']: len_a, len_b, len_c = phi, phi, 1 ang = pgon.angle() / 2 tan_a, r_a, R_a = get_belt_data(pgon, len_a, len_b) P = Vec(r_a, -len_a / 2, 0) Q = P + Vec(0, len_a, 0) points = [] for i in range(pgon.N): points.append(P.rot_z(2 * i * ang)) points.append(Q.rot_z(2 * i * ang)) tan_b, r_b, R_b = get_belt_data(pgon, len_b, len_a) r_c = len_c / (2 * tan(ang)) ht2 = gold_trap_ht**2 - (r_b - r_c)**2 # print(ht2, file=sys.stderr) if ht2 < -epsilon: raise ValueError('model is not constructible (height)') elif ht2 < 0: ht2 = 0 ht = math.sqrt(ht2) R_c = len_c / (2 * sin(ang)) V = Vec(R_c, 0, ht) N = pgon.N faces = [] if model_type not in ['3']: faces.append([2 * N + i for i in range(N)]) for i in range(pgon.N): points.append(V.rot_z(2 * i * ang)) if model_type in ['0', '1']: faces.append([3 * N + i for i in range(N)]) U = Vec(R_c, 0, -ht) for i in range(pgon.N): points.append(U.rot_z(2 * i * ang)) elif model_type in ['3']: faces.append([i for i in range(2 * N)]) for i in range(N): if model_type in ['0']: faces.append([2 * i, 3 * N + i, 2 * i + 1, 2 * N + i]) else: faces.append([2 * i, 2 * i + 1, 2 * N + i]) faces.append([ 2 * i + 1, (2 * i + 2) % (2 * N), 2 * N + ((i + 1) % N), 2 * N + i ]) if model_type in ['0', '1']: for i in range(N): if model_type in ['1']: faces.append([2 * i, 2 * i + 1, 3 * N + i]) faces.append([ 2 * i + 1, (2 * i + 2) % (2 * N), 3 * N + ((i + 1) % N), 3 * N + i ]) elif model_type in ['2']: belt_ht2 = gold_trap_ht**2 - (r_b - r_a)**2 if belt_ht2 < -epsilon: raise ValueError('model is not constructible (belt height)') elif belt_ht2 < 0: belt_ht2 = 0 belt_ht = math.sqrt(belt_ht2) for i, p in enumerate(points): points[i][2] += belt_ht / 2 points += [Vec(p[0], p[1], -p[2]).rot_z(ang) for p in points] faces += [[idx + 3 * N for idx in f] for f in faces] for i in range(2 * N): faces.append([ i, (i + 1) % (2 * N), 3 * N + i, 3 * N + (2 * N + i - 1) % (2 * N) ]) elif model_type in ['3']: for i, p in enumerate(points): points[i][2] -= ht points += [Vec(p[0], p[1], -p[2]) for p in points[:2 * N]] def new_v(v): v + 3 * N if v < 2 * N else v for i in range(len(faces)): faces.append([new_v(v) for v in faces[i]]) return points, faces
def make_ring(R, N, a): b = ring_ball_ang(N, a) P = Vec(R*math.sin(a-b), 0, R*math.cos(a-b)) return [P.rot_z(2*math.pi*i/N) for i in range(N)], b