Пример #1
0
 def test(axis, equiv_ang: Py_Angle):
     for ang in range(0, 360, 15):
         assert_rot(Matrix.axis_angle(axis, ang),
                    Matrix.from_angle(ang * equiv_ang),
                    f'{axis} * {ang} != {equiv_ang}')
         # Inverse axis = reversed rotation.
         assert_rot(Matrix.axis_angle(-axis, ang),
                    Matrix.from_angle(-ang * equiv_ang),
                    f'{-axis} * {ang} != {equiv_ang}')
Пример #2
0
def res_rotate_inst(inst: Entity, res: Property) -> None:
    """Rotate the instance around an axis.

    If `axis` is specified, it should be a normal vector and the instance will
    be rotated `angle` degrees around it.
    Otherwise, `angle` is a pitch-yaw-roll angle which is applied.
    `around` can be a point (local, pre-rotation) which is used as the origin.
    """
    angles = Angle.from_str(inst['angles'])
    if 'axis' in res:
        orient = Matrix.axis_angle(
            Vec.from_str(inst.fixup.substitute(res['axis'])),
            conv_float(inst.fixup.substitute(res['angle'])),
        )
    else:
        orient = Matrix.from_angle(
            Angle.from_str(inst.fixup.substitute(res['angle'])))

    try:
        offset = Vec.from_str(inst.fixup.substitute(res['around']))
    except NoKeyError:
        pass
    else:
        origin = Vec.from_str(inst['origin'])
        inst['origin'] = origin + (-offset @ orient + offset) @ angles

    inst['angles'] = (orient @ angles).to_angle()
Пример #3
0
def compute_orients(nodes: Iterable[Node]) -> None:
    """Compute the appropriate orientation for each node."""
    # This is based on the info at:
    # https://janakiev.com/blog/framing-parametric-curves/
    tangents: Dict[Node, Vec] = {}
    all_nodes: Set[Node] = set()
    for node in nodes:
        if node.prev is node.next is None:
            continue
        node_prev = node.prev if node.prev is not None else node
        node_next = node.next if node.next is not None else node
        tangents[node] = (node_next.pos - node_prev.pos).norm()
        all_nodes.add(node)

    while all_nodes:
        node1 = all_nodes.pop()
        node1 = node1.find_start()
        tanj1 = tangents[node1]
        # Start with an arbitrary roll for the first orientation.
        node1.orient = Matrix.from_angle(tanj1.to_angle())
        while node1.next is not None:
            node2 = node1.next
            all_nodes.discard(node2)
            tanj1 = tangents[node1]
            tanj2 = tangents[node2]
            b = Vec.cross(tanj1, tanj2)
            if b.mag_sq() < 0.001:
                node2.orient = node1.orient.copy()
            else:
                b = b.norm()
                phi = math.acos(Vec.dot(tanj1, tanj2))
                up = node1.orient.up() @ Matrix.axis_angle(
                    b, math.degrees(phi))
                node2.orient = Matrix.from_basis(x=tanj2, z=up)
            node1 = node2