Esempio n. 1
0
def calc_temcor_side(pgon, pyramid_ht, base_ht, freq):
    freq += 1
    inrad = pgon.inradius()
    axis = Vec(-inrad, 0, pyramid_ht)  # axis to rotate plane around
    A = Vec(0, 0, base_ht + pyramid_ht)  # apex
    B = Vec(inrad, 0.5, base_ht)  # base polygon vertex

    n0 = Vec.cross(A, B).unit()

    edge_ang = anti_lib.angle_around_axis(Vec(B[0], 0, B[2]), B, axis)
    ang_inc = edge_ang / freq

    points = []
    faces = []
    for i in range(freq):
        n_inc = Mat.rot_axis_ang(axis, i * ang_inc) * Vec(0, 1, 0)
        edge_v = Vec.cross(n_inc, n0).unit()
        last_idx = i * (i - 1) // 2
        new_idx = i * (i + 1) // 2
        for j in range(i + 1):
            v = Mat.rot_axis_ang(axis, -2 * j * ang_inc) * edge_v
            points.append(v)
            if new_idx and j < i:
                faces.append([new_idx + j, new_idx + j + 1, last_idx + j])
            if j < i - 1:
                faces.append([new_idx + j + 1, last_idx + j + 1, last_idx + j])

    return (points, faces)
Esempio n. 2
0
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
Esempio n. 3
0
def calculate_belt_points(pgon, model_type):
    ang = pgon.angle() / 2
    tan_a = math.sin(ang) / (math.cos(ang) + phi)  # half of unit edge
    P = Vec(1 / (2 * tan_a), -1 / 2, 0)
    tan_b = math.sin(ang) / (math.cos(ang) + 1 / phi)  # half of phi edge
    Q = Vec(phi / (2 * tan_b), -phi / 2, 0)
    bar_ht = math.cos(math.pi / 10)  # planar height of pentagon "bar"
    diff_r = P[0] - Q[0]
    try:
        ht0 = math.sqrt(bar_ht**2 - diff_r**2) / 2
    except:
        raise ValueError('model is not constructible')

    P[2] = -ht0
    Q[2] = ht0
    pent_ht = math.sqrt(5 + 2 * math.sqrt(5)) / 2  # planar height of pentagon
    x_cap = P[0] - pent_ht * (diff_r / bar_ht)
    z_cap = -ht0 + pent_ht * ((2 * ht0) / bar_ht)
    R = Vec(x_cap, 0, z_cap)
    S = Vec(x_cap * math.cos(ang), x_cap * math.sin(ang), -z_cap)
    cap_inrad = x_cap * math.cos(ang)
    apex_ht = 0
    if model_type == 'a':
        try:
            apex_ht = z_cap + cap_inrad * (z_cap + P[2]) / (P[0] - cap_inrad)
        except:
            raise ValueError('could not calculate apex height')
    A = Vec(0, 0, apex_ht)
    return [P, Q, R, S, A]
Esempio n. 4
0
def j88_get_principal_verts(pgon, ang, flags):
    bad = flags.strip('AB')
    if bad:
        raise ValueError('Unrecognised form flag(s) \'' + bad + '\'')
    ridge = 'A' not in flags
    belt_back = 'B' in flags
    A, B, B2, C = get_pstts_cap_verts(pgon, ang, ridge)

    p_ang = pgon.angle() / 2
    sq_mid = (B + B2.rot_z(2 * p_ang)) / 2
    sq_mid_rad = Vec(sq_mid[0], sq_mid[1], 0).mag()
    A_rad = A[0]
    tri_ht2 = 3 * edge / 4 - (A_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(A_rad, 0, A2_ht).rot_z(p_ang)

    mid_B_B1 = Vec(B[0], 0, B[2])
    ax = C - mid_B_B1
    rot = Mat.rot_axis_ang(ax, math.pi)
    pt = A - mid_B_B1
    C2 = rot * pt + mid_B_B1

    return A, B, B2, C, A2, C2
Esempio n. 5
0
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
Esempio n. 6
0
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]]
Esempio n. 7
0
def make_equ_antiherm(pgon, dih_ang):
    """Make a hermaphrodite with equilateral triangles"""
    N = pgon.N
    a = pgon.angle()/2
    R = pgon.circumradius()
    tri_alt = sqrt(3)/2
    tri_ht = tri_alt * sin(dih_ang)
    R2 = pgon.inradius() + tri_alt * cos(dih_ang)

    points = [Vec(0, 0, 0)]*(2*N+1)
    for i in range(N):
        points[i] = Vec(R*cos(2*i*a), R*sin(2*i*a), 0)
        points[i+N] = Vec(R2*cos(2*i*a+a), R2*sin(2*i*a+a), tri_ht)

    A = sqrt(points[0][0]**2 + points[0][1]**2)
    mid = anti_lib.centroid([points[N], points[2*N-1]])
    B = sqrt(mid[0]**2 + mid[1]**2)
    z_diff = mid[2] - points[0][2]
    points[2*N][2] = A * z_diff / (A - B)

    faces = []
    faces.append([i for i in range(N)])      # bottom

    for i in range(N):
        faces.append([i, (i + 1) % N, N + i])
        faces.append([N + i, 2*N, N + (i + 1) % N, (i + 1) % N])

    return points, faces
Esempio n. 8
0
def rot_reflect_pair(points, pgon, d, rev=False):
    mat0 = Mat.rot_axis_ang(Vec(0, 0, 1), (d + 0.5) * pgon.angle())
    pts = [mat0 * Vec(p[0], p[1], -p[2]) for p in points]
    mat1 = Mat.rot_axis_ang(Vec(0, 0, 1), d * pgon.angle())
    if rev:
        return [mat1 * p for p in points] + pts
    else:
        return pts + [mat1 * p for p in points]
Esempio n. 9
0
def get_tetrahedron(verts, faces):
    """Return an tetrahedron"""
    X = 1 / math.sqrt(3)
    verts.extend(
        [Vec(-X, X, -X),
         Vec(-X, -X, X),
         Vec(X, X, X),
         Vec(X, -X, -X)])
    faces.extend([(0, 1, 2), (0, 3, 1), (0, 2, 3), (2, 1, 3)])
Esempio n. 10
0
def get_default_angle(pgon, radius_top, radius_bottom, height):
    a = pgon.angle() / 2
    P1 = Vec(radius_top, 0, height)
    Q1 = Vec(radius_bottom * cos(a), radius_bottom * sin(a), 0.0)
    Q2 = Vec(radius_bottom * cos(-a), radius_bottom * sin(-a), 0.0)
    v0 = (Q1 - P1).unit()
    v1 = (Q2 - P1).unit()
    cos_a = anti_lib.safe_for_trig(Vec.dot(v0, v1))
    ang = acos(cos_a)
    return pi - ang
Esempio n. 11
0
def get_principal_verts(p_ang, ang, cross_flag):
    """Calculate example vertex coordinates"""
    edge = 1                                    # polygon edge length
    rad = edge/(2*sin(p_ang))                   # circumradius of base polygon
    belt_irad = edge*cos(ang)/(2*tan(p_ang/2))  # inradius of belt polygon
    tri_ht = edge * sqrt(3)/2

    # Cut polygon cylinder (radius rad) by plane normal to a belt edge
    # and the through its centre point
    # Distance to this ellipse should be tri_ht
    S2 = sin(ang)**2
    if abs(S2) < EPSILON:
        x = (1-2*cross_flag)*rad

        val = tri_ht**2 - (belt_irad - x)**2
        if val < -EPSILON:
            raise ValueError('triangle cannot reach base polygon '
                             '(2nd coordinate)')
        elif val < 0.0:
            val = 0.0

        y = sqrt(val)

    else:
        a = (1-S2)
        b = 2*belt_irad*S2
        c = S2*tri_ht**2 - rad**2 - S2*belt_irad**2

        disc = b**2 - 4*a*c
        if disc < - EPSILON:
            raise ValueError('triangle cannot reach base polygon '
                             '(1st coordinate)')
        elif disc < 0.0:
            disc = 0.0

        if not a:
            raise ValueError('triangle cannot reach base polygon '
                             '(vertical edges)')

        x = (-b + (1-2*cross_flag)*sqrt(disc))/(2*a)

        val = (rad**2 - x**2)/S2
        if val < -EPSILON:
            raise ValueError('triangle cannot reach base polygon '
                             '(2nd coordinate)')
        elif val < 0.0:
            val = 0.0

        y = sqrt(val)

    return (Vec(x, y*sin(ang), y*cos(ang)),                          # base
            Vec(belt_irad, 0.5*edge*cos(ang), 0.5*edge*sin(ang)))    # belt
Esempio n. 12
0
def main():
    """Entry point"""
    parser = argparse.ArgumentParser(description=__doc__)

    parser.add_argument('num_balls_on_ring',
                        help='Number of balls on each ring',
                        type=int,
                        nargs='?',
                        default=10)
    parser.add_argument('-o',
                        '--outfile',
                        help='output file name (default: standard output)',
                        type=argparse.FileType('w'),
                        default=sys.stdout)

    args = parser.parse_args()

    ring_centres = read_coords()
    if not len(ring_centres):
        parser.error('no coordinates in input')

    R = ring_centres[0].mag()
    dist = find_minimum_separation(ring_centres)
    a = math.asin(dist / (2 * R))
    ball_points, ball_ang = make_ring(R, args.num_balls_on_ring, a)
    print('ball radius = %.14f' % (2 * R * math.sin(ball_ang / 2)),
          file=sys.stderr)

    out = anti_lib.OffFile(args.outfile)
    out.print_header(len(ring_centres) * len(ball_points), 0)
    for cent in ring_centres:
        mat = Mat.rot_from_to(Vec(0, 0, 1), cent)
        out.print_verts([mat * p for p in ball_points])
Esempio n. 13
0
def read_coords():
    points = []
    while 1:
        line = sys.stdin.readline()
        if line == '\n':
            continue

        if line == "":
            break

        m = re.search('^ *([^ ,]+) *,? *([^ ,]+) *,? *([^ ,\n]+) *$', line)
        if not m:
            sys.stderr.write(
                'error: did not find x, y and z values in following '
                'line (1):\n')
            sys.stderr.write(line)
            sys.exit(1)
        else:
            try:
                points.append(
                    Vec(*[float(m.group(i)) for i in range(1, 3 + 1)]))
            except:
                sys.stderr.write(
                    'error: did not find x, y and z values in following '
                    'linei (2):\n')
                sys.stderr.write(line)
                sys.exit(1)

    return points
Esempio n. 14
0
def calc_points(args):
    points = []
    number_turns = args.number_turns
    if not number_turns:
        number_turns = 1e-12
    if args.distance_between_points:
        rad = 2 * args.distance_between_points
    else:
        # half distance between turns on a rad 1 sphere
        rad = 2 * math.sqrt(1 - math.cos(math.pi / (number_turns - 1)))
    a0 = 0
    cur_point = Vec(0.0, 1.0, 0.0)
    points.append(cur_point)

    delt = math.atan(rad / 2) / 10
    a1 = a0 + .0999999 * delt  # still within sphere
    while a1 < math.pi:
        if (cur_point - angle_to_point(a1, number_turns)).mag() > rad:
            a0 = psearch(a1 - delt, a1, a0, rad, number_turns)
            cur_point = angle_to_point(a0, number_turns)
            points.append(cur_point)
            a1 = a0

        a1 += delt

    return points
Esempio n. 15
0
def angle_to_point(a, number_turns):
    a2 = 2 * a * number_turns  # angle turned around y axis
    r = math.sin(a)  # distance from y axis
    y = math.cos(a)
    x = r * math.sin(a2)
    z = r * math.cos(a2)
    return Vec(x, y, z)
Esempio n. 16
0
def make_verts(lat_type, width, container_is_cube):
    """Generate coordinates"""
    verts = []
    if container_is_cube:
        coords_start = 0
    else:  # sphere
        coords_start = -width
    coords_end = width

    coord_test = eval(lat_type + "_coord_test")
    for x in range(coords_start, coords_end + 1):
        for y in range(coords_start, coords_end + 1):
            for z in range(coords_start, coords_end + 1):
                if container_is_cube or dist2_inside(Vec(x, y, z), width):
                    if coord_test(x, y, z):
                        verts.append(Vec(x, y, z))
    return verts
Esempio n. 17
0
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
Esempio n. 18
0
def calc_points(args):
    points = []
    vert_ang_inc = math.pi/(args.number_circles-1)
    ball_dia = math.sqrt(2 - 2*math.cos(vert_ang_inc))
    num_circles = args.number_circles
    horz_stagger = 0.0
    circles = []
    for circle in range(num_circles):
        if args.points_list:
            num_balls = args.points_list[circle]
            if num_balls == -1:
                num_balls = args.default_number_points
        else:
            num_balls = args.default_number_points

        vert_ang = circle*vert_ang_inc
        if num_balls == -1:
            rad = math.sin(vert_ang)
            try:
                num_balls = int(math.floor(2*math.pi /
                                math.acos((2*rad*rad-ball_dia*ball_dia) /
                                          (2*rad*rad)) * args.aspect_ratio))
            except:
                num_balls = 1

        horz_ang_inc = 2*math.pi/num_balls if num_balls > 0 else 0
        circles.append([vert_ang, num_balls, horz_ang_inc, 0.0])

    if args.stagger:
        for circle in range(num_circles//2, -1, -1):
            if circle == num_circles//2:
                circles[circle][3] = circles[circle][2]/4
                circles[circle+1][3] = -circles[circle][2]/4
            else:
                for circ in [[circle, circle+1],
                             [num_circles-circle-1, num_circles-circle-2]]:
                    horz_stagger = circles[circ[1]][3]
                    if horz_stagger > 0:
                        horz_stagger -= circles[circ[1]][2]/2
                    else:
                        horz_stagger += circles[circ[1]][2]/2
                    circles[circ[0]][3] = horz_stagger

    for circle in range(args.exclude_poles, num_circles-args.exclude_poles):
        vert_ang = circles[circle][0]
        num_balls = circles[circle][1]
        horz_ang_inc = circles[circle][2]
        horz_stagger = circles[circle][3]
        rad = math.sin(vert_ang)

        for n in range(num_balls):
            horz_ang = n*horz_ang_inc+horz_stagger
            points.append(Vec(rad*math.cos(horz_ang), rad*math.sin(horz_ang),
                              math.cos(vert_ang)))

    return points
Esempio n. 19
0
def make_frame(frame_elems, axis_angle, rad, num_segs):
    points = []
    faces = []
    if frame_elems:
        v0 = Vec(0, 0, -1)
        v1 = Vec(math.sin(axis_angle), 0, -math.cos(axis_angle))
        if 'r' in frame_elems:
            ps, fs = make_arc(v0, v1, num_segs, 0)
            points += ps
            faces += fs
        if 'a' in frame_elems:
            num_pts = len(points)
            points += [v0, -v0, v1, -v1]
            faces += [[num_pts + 0, num_pts + 1], [num_pts + 2, num_pts + 3]]

        points = [rad * p for p in points]
        faces += [[i] for i in range(len(points))]

    return points, faces
Esempio n. 20
0
def calc_polygons2(pgon0, r0, ang, pgon1, r1, angle_between_axes):
    # rotate initial vertex of polygon0 by ang. Common
    # point lies on a line through vertex in the direction
    # of axis0 (z-axis). Common vertex lies on a cylinder
    # radius r1 with axis on axis1.

    # rotate model so axis1 is on z-axis, to simplify the
    # calculation of the intersection
    rot = Mat.rot_axis_ang(Vec(0, 1, 0), angle_between_axes)

    # initial vertex turned on axis
    V = Vec(r0, 0, 0).rot_z(ang)
    # vertex in rotated model
    Q = rot * V
    # direction of line in rotated model
    u = rot * Vec(0, 0, 1)

    # equation of line is P = Q + tu for components x y z and parameter t
    # equation of cylinder at z=0 is x^2 + y^2 = r1^2
    a = u[0]**2 + u[1]**2
    b = 2 * (Q[0] * u[0] + Q[1] * u[1])
    c = Q[0]**2 + Q[1]**2 - r1**2

    disc = b**2 - 4 * a * c
    if disc < -epsilon:
        raise Exception("model is not geometrically constructible")
    elif disc < 0:
        disc = 0

    t = (-b - math.sqrt(disc)) / (2 * a)  # negative gives most distant point

    P = V + Vec(0, 0, t)  # the common point

    points = []
    points += [P.rot_z(i * pgon0.angle()) for i in range(pgon0.N)]
    faces = [[i for i in range(pgon0.N)]]

    Q = rot * P
    rot_inv = Mat.rot_axis_ang(Vec(0, 1, 0), -angle_between_axes)
    points += [rot_inv * Q.rot_z(i * pgon1.angle()) for i in range(pgon1.N)]
    faces += [[i + pgon0.N for i in range(pgon1.N)]]

    return points, faces
Esempio n. 21
0
def make_hexagonal_tiling(freq):
    grads = freq + 1
    points = [[0, 0, 0]]
    faces = []
    for i in range(6):
        rot = Mat.rot_axis_ang(Vec(0, 0, 1), i * math.pi / 3)
        for j in range(1, grads):
            points.append(rot * Vec(j, 0, 0))

    for t in range(6):
        p1 = ((t + 1) % 6) * freq + 1
        p2 = t * freq + 1
        vec = points[p1] - points[p2]
        for i in range(1, freq):
            for j in range(0, i):
                points.append(points[t * freq + 1 + i] + vec * (j + 1))
        faces += get_tri_faces(t, freq)

    return points, faces, points[freq].mag()
Esempio n. 22
0
def make_sq_x_tiling(freq):
    points = []
    faces = []
    grads = 2 * freq + 1
    for i in range(grads):
        for j in range(grads):
            points.append(Vec(i - freq, j - freq, 0))
    for i in range(grads - 1):
        for j in range(grads - 1):
            cent_idx = len(points)
            points.append(Vec(i - freq + 0.5, j - freq + 0.5, 0))
            face = [
                j + i * grads, j + 1 + i * grads, j + 1 + (i + 1) * grads,
                j + (i + 1) * grads
            ]
            for v in range(4):
                faces.append([face[v], face[(v + 1) % 4], cent_idx])

    return points, faces, points[0].mag()
Esempio n. 23
0
def bifrustum_model(pgon, arg_type):
    """Construct bifrustum model with golden trapziums"""
    N = pgon.N
    ang = pgon.angle() / 2
    R0 = phi / (2 * sin(ang))
    R1 = 1 / (2 * sin(ang))
    ht = sqrt(phi**2 - (R0 - R1)**2)
    points = []
    points += [Vec(R0, 0, ht).rot_z(2 * i * ang) for i in range(N)]
    points += [Vec(R1, 0, 0).rot_z(2 * i * ang) for i in range(N)]
    points += [Vec(R0, 0, -ht).rot_z(2 * i * ang) for i in range(N)]

    faces = []
    faces.append([i for i in range(N)])
    faces.append([i + 2 * N for i in range(N)])
    for i in range(N):
        faces.append([i, (i + 1) % N, N + (i + 1) % N, N + i])
        faces.append([N + i, N + (i + 1) % N, 2 * N + (i + 1) % N, 2 * N + i])
    return points, faces
Esempio n. 24
0
def calc_polygons(pgon, ang, angle_between_axes, sign_flag=1):
    # rotate initial vertex of first polygon by ang. Common
    # point lies on a line through vertex in the direction
    # of first axis (z-axis). Common point lies on a cylinder
    # with the circumradius for radius and second axis for axis.

    # rotate model so axis1 is on z-axis, to simplify the
    # calculation of the intersection
    rot = Mat.rot_axis_ang(Vec(0, 1, 0), angle_between_axes)

    R = pgon.circumradius()
    V = Vec(R, 0, 0).rot_z(ang)  # initial vertex turned on axis
    Q = rot * V  # vertex in rotated model
    u = rot * Vec(0, 0, 1)  # direction of line in rotated model

    # equation of line is P = Q + tu for components x y z and parameter t
    # equation of cylinder at z=0 is x^2 + y^2 = r1^2
    a = u[0]**2 + u[1]**2
    b = 2 * (Q[0] * u[0] + Q[1] * u[1])
    c = Q[0]**2 + Q[1]**2 - R**2

    disc = b**2 - 4 * a * c
    if disc < -epsilon:
        raise Exception("model is not geometrically constructible")
    elif disc < 0:
        disc = 0

    # The sign flag, which changes for the range 90 to 270 degrees, allows
    # the model to reverse, otherwise the model breaks apart in this range.
    t = (-b + sign_flag * math.sqrt(disc)) / (2 * a)

    P = V + Vec(0, 0, t)  # the common point

    points = pgon.get_points(P)
    faces = pgon.get_faces()

    Q = rot * P
    rot_inv = Mat.rot_axis_ang(Vec(0, 1, 0), -angle_between_axes)
    points += [rot_inv * p for p in pgon.get_points(Q)]
    faces += pgon.get_faces(pgon.N * pgon.parts)

    return points, faces
Esempio n. 25
0
def calc_polygons(pgon0, pgon1, ang, ratio, angle_between_axes):
    # rotate initial vertex of polygon0 by ang. Common
    # point lies on a line through vertex in the direction
    # of axis0 (z-axis). Common vertex lies on a cylinder
    # radius r1 with axis on axis1.

    # rotate model so axis1 is on z-axis, to simplify the
    # calculation of the intersection
    rot = Mat.rot_axis_ang(Vec(0, 1, 0), angle_between_axes)

    # initial vertex turned on axis
    V = Vec(pgon0.circumradius(), 0, 0).rot_z(ang)
    # vertex in rotated model
    Q = rot * V
    # direction of line in rotated model
    u = rot * Vec(0, 0, 1)

    # equation of line is P = Q + tu for components x y z and parameter t
    # equation of cylinder at z=0 is x^2 + y^2 = r1^2
    a = u[0]**2 + u[1]**2
    b = 2 * (Q[0] * u[0] + Q[1] * u[1])
    c = Q[0]**2 + Q[1]**2 - (pgon1.circumradius() * ratio)**2

    disc = b**2 - 4 * a * c
    if disc < -epsilon:
        raise Exception("model is not geometrically constructible")
    elif disc < 0:
        disc = 0

    t = (-b - math.sqrt(disc)) / (2 * a)

    P = V + Vec(0, 0, t)  # the common point

    points = pgon0.get_points(P)
    faces = pgon0.get_faces()

    Q = rot * P
    rot_inv = Mat.rot_axis_ang(Vec(0, 1, 0), -angle_between_axes)
    points += [rot_inv * p for p in pgon1.get_points(Q)]
    faces += pgon1.get_faces(pgon0.N * pgon0.parts)

    return points, faces
Esempio n. 26
0
def parallel_project(points, R, rad):
    new_points = []
    for point in points:
        x = point[0] * rad / R
        y = point[1] * rad / R
        try:
            z = math.sqrt(1 - (x**2 + y**2))
        except:
            z = 0
        new_points.append(Vec(x, y, -z))
    return new_points
Esempio n. 27
0
def make_jitterbug(pgon, ang, cross, right_fill, left_fill, delete_main_faces):
    """Make the jitterbug model"""
    p_ang = pgon.angle()/2
    A, B = get_principal_verts(p_ang, ang, cross)

    A2 = Vec(A[0], -A[1], -A[2]).rot_z(-p_ang)
    A = Vec(A2[0], A2[1], -A2[2]).rot_z(p_ang)
    B2 = Vec(B[0], -B[1], -B[2])

    N = pgon.N
    points = []
    for pt in [A, A2, B2, B]:
        points += [pt.rot_z(i*2*p_ang) for i in range(N)]

    faces = []
    if not delete_main_faces:
        faces.append([i for i in range(N)])          # top
        faces.append([2*N-1 - i for i in range(N)])  # bottom

        # side triangles
        for i in range(N):
            faces.append([2*N+i, 3*N+i, (i+N) % N])
            faces.append([3*N+i, 2*N+(i+1) % N, N + (i+1+N) % N])

    # fill holes
    # Top hole: i, (i+1) % N, 2*N+(i+1) % N, 3*N+i
    # Bottom hole: N+i, N+(i-1+N) % N, 2*N+(i-1+N) % N, 3*N+(i-1) % N
    if right_fill:
        for i in range(N):
            faces.append([(i+1) % N, i, 3*N+i])
            faces.append([3*N+i, (i+1) % N, 2*N+(i+1) % N])
            faces.append([N+(i-1+N) % N, N+i, 2*N+(i-1+N) % N])
            faces.append([2*N+(i-1+N) % N, N+i, 3*N+(i-1) % N])
    if left_fill:
        for i in range(N):
            faces.append([i, (i+1) % N, 2*N+(i+1) % N])
            faces.append([2*N+(i+1) % N, 3*N+i, i])
            faces.append([N+i, N+(i-1+N) % N, 3*N+(i-1) % N])
            faces.append([3*N+(i-1) % N, 2*N+(i-1+N) % N, N+(i-1+N) % N])

    return points, faces
Esempio n. 28
0
def make_sq_tiling(freq):
    points = []
    faces = []
    grads = 2 * freq + 1
    for i in range(grads):
        for j in range(grads):
            points.append(Vec(i - freq, j - freq, 0))
            if i < grads - 1 and j < grads - 1:
                faces.append([
                    j + i * grads, j + 1 + i * grads, j + 1 + (i + 1) * grads,
                    j + (i + 1) * grads
                ])
    return points, faces, points[0].mag()
Esempio n. 29
0
def tri_antiprism_pt(pgon, a, b, c):
    """Return construct point for antiprism model"""
    s = (a + b + c) / 2
    alt = 2 * math.sqrt(s * (s - a) * (s - b) *
                        (s - c)) / a  # planar height of A
    ang = pgon.angle() / 2
    R = pgon.circumradius(a)  # polygon circumradius (side a)
    r = pgon.inradius(a)  # polygon inradius (side a)
    a0 = math.sqrt(b**2 - alt**2)  # from C to perpendicular from A
    y = a0 - a / 2
    x = math.sqrt(R**2 - y**2)
    alt_proj_x = x - r  # projection of alt onto x dir
    z = math.sqrt(alt**2 - alt_proj_x**2) / 2
    ang_to_A = math.atan2(y, x)  # adjust point for dih axis
    ang_off = (ang_to_A - ang) / 2
    return Vec(x, y, z).rot_z(-ang_off)
Esempio n. 30
0
def project_onto_sphere(points, ht, proj_ht):
    new_points = []
    for point in points:
        a = point[0]
        b = point[1]
        d = ht - proj_ht
        if abs(d) < epsilon:
            z = 1
            x = 0
            y = 0
        else:
            z = (a**2 + b**2 - d**2) / (a**2 + b**2 + d**2)
            x = a * (z - 1) / d
            y = b * (z - 1) / d

        new_points.append(Vec(x, y, -z))
    return new_points