예제 #1
0
def _compute_margulis_tube_ends(tet, vertex):
    trig = tet.horotriangles[vertex]
    CF = tet.ShapeParameters[t3m.E01].parent()

    if tet.Class[vertex].is_complete:
        return [(0.0, 0.0, 0.0, 0.0), (0.0, 0.0, 0.0, 0.0)]

    tet_vertices = [
        tet.complex_vertices[v] for v in t3m.ZeroSubsimplices if v != vertex
    ]

    cusp_vertices = [
        trig.vertex_positions[vertex | v] for v in t3m.ZeroSubsimplices
        if v != vertex
    ]

    std_to_tet = _matrix_taking_0_1_inf_to_given_points(*tet_vertices)
    cusp_to_std = _adjoint(
        _matrix_taking_0_1_inf_to_given_points(*cusp_vertices))

    cusp_to_tet = std_to_tet * cusp_to_std

    cusp_to_tet_O13 = GL2C_to_O13(cusp_to_tet)

    return [cusp_to_tet_O13 * vector([1.0, x, 0.0, 0.0]) for x in [-1.0, 1.0]]
예제 #2
0
def _compute_margulis_tube_ends(tet, vertex):
    
    if tet.Class[vertex].is_complete:
        return [(0.0, 0.0, 0.0, 0.0), (0.0, 0.0, 0.0, 0.0)]
    
    return [ tet.cusp_to_tet_matrices[vertex] * vector([1.0, x, 0.0, 0.0])
             for x in [-1.0, 1.0] ]
예제 #3
0
    def _compute_edge_ends(self):
        cs = [vector(self.RF, [1, 1, 0, 0]), vector(self.RF, [1, -1, 0, 0])]

        def _compute_edge_ends(tet, perm):
            m = tet.permutahedron_matrices[perm]
            return [GL2C_to_O13(_adjoint(m)) * c for c in cs]

        for tet in self.mcomplex.Tetrahedra:
            tet.R13_edge_ends = {
                t3m.E01: _compute_edge_ends(tet, (0, 1, 2, 3)),
                t3m.E02: _compute_edge_ends(tet, (0, 2, 1, 3)),
                t3m.E12: _compute_edge_ends(tet, (2, 1, 0, 3)),
                t3m.E03: _compute_edge_ends(tet, (0, 3, 1, 2)),
                t3m.E13: _compute_edge_ends(tet, (1, 3, 0, 2)),
                t3m.E23: _compute_edge_ends(tet, (2, 3, 0, 1))
            }
예제 #4
0
 def _check_consistency(self):
     for tet in self.mcomplex.Tetrahedra:
         for F in t3m.TwoSubsimplices:
             for V in t3m.ZeroSubsimplices:
                 if V & F:
                     v0 = tet.O13_matrices[F] * vector(tet.R13_vertices[V])
                     v1 = tet.Neighbor[F].R13_vertices[tet.Gluing[F].image(V)]
                     err = R13_dot(v0, v1)
                     if err > 1e-10 or err < -1e-10:
                         print("PROBLEM")
예제 #5
0
def edge_involution(u, v):
    b0 = vector(R13_normalise(u + v))
    b1 = u - v
    b1 = vector(R13_normalise(b1 + b0 * R13_dot(b0, b1)))
    candidates = [ [ 0, 1, 0, 0], [ 0, 0, 1, 0], [ 0, 0, 0, 1] ]
    penalties_and_candidates = [ (abs(R13_dot(b1, c)), vector(c)) for c in candidates ]
    penalties_and_candidates.sort()
    b2 = penalties_and_candidates[0][1]
    b3 = penalties_and_candidates[1][1]
    
    b2 = vector(R13_normalise(b2 + b0 * R13_dot(b0, b2) - b1 * R13_dot(b1, b2)))
    b3 = vector(R13_normalise(b3 + b0 * R13_dot(b0, b3) - b1 * R13_dot(b1, b3) - b2 * R13_dot(b2, b3)))
                
    bs = [ b0, b1, b2, b3 ]

    m = [ matrix([[x * y for x in _change_first_sign(b)]
                  for y in b]) for b in bs ]

    return - m[0] + m[1] - m[2] - m[3]
예제 #6
0
    def _check_consistency(self):
        for tet in self.mcomplex.Tetrahedra:
            for F in t3m.TwoSubsimplices:
                for V in t3m.ZeroSubsimplices:
                    if V & F:
                        v0 = tet.O13_matrices[F] * vector(tet.R13_vertices[V])
                        v1 = tet.Neighbor[F].R13_vertices[tet.Gluing[F].image(
                            V)]

                        if abs(R13_dot(v0, v1) - (-1.0)) > 1e-6:
                            print("Inconsistency ", tet.Index, F)
                            print(v0)
                            print(v1)
예제 #7
0
    def _compute_tet_vertices(self):
        c = vector(self.RF, [1, 0, 0, 0])

        def _compute_vertex(tet, perm):
            m = tet.permutahedron_matrices[perm]
            return GL2C_to_O13(_adjoint(m)) * c

        for tet in self.mcomplex.Tetrahedra:
            tet.R13_vertices = {
                t3m.V0: _compute_vertex(tet, (0, 1, 3, 2)),
                t3m.V1: _compute_vertex(tet, (1, 0, 2, 3)),
                t3m.V2: _compute_vertex(tet, (2, 0, 3, 1)),
                t3m.V3: _compute_vertex(tet, (3, 0, 1, 2))
            }
예제 #8
0
    def _compute_planes(self):
        c = vector(self.RF, [0.0, 0.0, 0.0, -1.0])

        def _compute_plane(tet, perm):
            m = tet.permutahedron_matrices[perm]
            v = c * GL2C_to_O13(m)
            return vector([-v[0], v[1], v[2], v[3]])

        for tet in self.mcomplex.Tetrahedra:
            tet.R13_planes = {
                t3m.F0: _compute_plane(tet, (2, 3, 1, 0)),
                t3m.F1: _compute_plane(tet, (0, 3, 2, 1)),
                t3m.F2: _compute_plane(tet, (0, 1, 3, 2)),
                t3m.F3: _compute_plane(tet, (0, 2, 1, 3))
            }
예제 #9
0
def complex_to_pair(z):
    return vector([z.real(), z.imag()])
예제 #10
0
    def compute_translation_and_inverse_from_pick_point(
            self, size, frag_coord, depth):

        # Depth value emitted by shader is tanh(distance from camera)

        # Limit the maximal depth for orbiting to avoid numeric issues
        depth = min(depth, _max_depth_for_orbiting)

        fov = self.ui_uniform_dict['fov'][1]
        isIdeal = self.ui_parameter_dict['perspectiveType'][1]

        # Reimplement functionality from fragment shader

        # See get_ray_eye_space
        fov_scale = 2.0 * math.tan(fov / 360.0 * math.pi)

        # Reimplement computation of xy from fragment coordinate
        x = (frag_coord[0] - 0.5 * size[0]) / size[0]
        y = (frag_coord[1] - 0.5 * size[1]) / size[0]

        # Reimplement get_ray_eye_space to determine end point of
        # ray. The end point is encoded as pair distance to origin
        # direction to origin.
        if isIdeal:
            scaled_x = 0.5 * fov_scale * x
            scaled_y = 0.5 * fov_scale * y

            # Use "parabolic transformation magic by Saul"
            # to determine the start point and direction of ray.
            # Then compute end point using depth value.
            foo = 0.5 * (scaled_x * scaled_x + scaled_y * scaled_y)
            rayEnd = R13_normalise(
                vector([
                    RF((foo + 1.0) + depth * foo),
                    RF(scaled_x + depth * scaled_x),
                    RF(scaled_y + depth * scaled_y),
                    RF(foo + depth * (foo - 1.0))
                ]))

            # Distance of rayEnd from origin
            dist = math.acosh(rayEnd[0])
            # Direction from origin to rayEnd
            dir = vector([rayEnd[1], rayEnd[2], rayEnd[3]])
        else:
            scaled_x = fov_scale * x
            scaled_y = fov_scale * y

            # Camera is assumed to be at origin.
            dist = math.atanh(depth)
            # Reimplemented from get_ray_eye_space
            dir = vector([RF(scaled_x), RF(scaled_y), RF(-1.0)])

        # Normalize direction
        dir = dir.normalized()

        # Compute the circumference of a circle of radius dist
        #
        # Do this by using a concentric circle in the Poincare disk
        # model
        poincare_dist = math.tanh(dist / 2.0)
        hyp_circumference_up_to_constant = (
            poincare_dist / (1.0 - poincare_dist * poincare_dist))

        speed = min(
            _max_orbit_speed, _max_linear_camera_speed /
            max(1e-10, hyp_circumference_up_to_constant))

        # Compute translation along direction by distance.
        # And inverse.
        return (unit_3_vector_and_distance_to_O13_hyperbolic_translation(
            dir, dist),
                unit_3_vector_and_distance_to_O13_hyperbolic_translation(
                    dir, -dist), speed)
예제 #11
0
 def _compute_plane(tet, perm):
     m = tet.permutahedron_matrices[perm]
     v = c * GL2C_to_O13(m)
     return vector([-v[0], v[1], v[2], v[3]])