Beispiel #1
0
    def _create_clip_paths( self ):
        paths = svg.element( 'g', { 'class' : 'clip_paths' } )

        key_edge = self.radius / 2
        edge = svg.format_value( key_edge )

        for ( index, shape ) in enumerate( _key_shapes ):
            key_width  = self.xscale * shape[ 0 ]
            key_height = self.yscale * shape[ 1 ]
            width  = svg.format_value( key_width  - ( 2 * key_edge ) )
            height = svg.format_value( key_height - ( 2 * key_edge ) )
            paths.append_child(
                svg.element(
                    'clipPath',
                    { 'id' : ( 'clip_%d' % index ) },
                    [
                        # ZIH - messy since it depends on _make_key_paths()
                        svg.element(
                            'rect',
                            {
                                'x'      : edge,
                                'y'      : edge,
                                'rx'     : edge,
                                'ry'     : edge,
                                'width'  : width,
                                'height' : height
                            }
                        )
                    ]
                )
            )

        return paths
Beispiel #2
0
    def create_svg( self, title = 'keyboard' ):

        width  = self.xscale * keyboard._unit_columns
        height = self.yscale * ( _row_offsets[ -1 ] + 1.0 )

        image = svg.create_image( width, height, title )

        image.append_child(
            svg.element(
                'link',
                {
                    'rel' : 'icon', 'href' : '#key_0',
                    'xmlns' : 'http://www.w3.org/1999/xhtml'
                }
            )
        )

        image.append_child(
            svg.element( 'style', { 'type' : 'text/css' }, str( self.style ) )
        )

        image.append_child( self._create_key_shapes() )

        image.append_child( self._create_clip_paths() )

        image.append_child( self._create_layout() )

        return image
Beispiel #3
0
def patch_path(patch, colour):
    pathd = [
        'M',
    ]
    for point in PATCHES[patch]:
        coord = get_coord(point)
        pathd.append(coord.x)
        pathd.append(coord.y)
    pathd.append('z')
    return svg.element('path', id=patch, d=pathd, fill=gc.COLOURS[colour])
Beispiel #4
0
def oll(x, rotate=0, filename="oll.svg"):
    """
        Generates OLL images.  

        x: state code.  

        rotate: rotation angle, clockwise, in [-270, -180, -90, 0, 90, 180, 270].  

        filename: SVG filename.

        State code (x) syntax:
          1. int, OLL code, 1~57.
          2. 9-char string, specifying orientation of the 9 pieces (ULB, UB, URB, ..., ULR), 
             for example OLL20 (X-shaped) = 'ubulurufu'. Case-insensitive.
          3. list of 3-char strings. Each string specifies a 'colour patch',
             for example OLL20 = ['lbu', 'mbb', 'rbu', 'lsl', ..., 'rfu'].  
             Format: [lmr][bsf][ulrbf]
             The 1st and 2nd char specifies the position of the corner/edge/centre piece, and the 3rd char specifies its orientation. Case-insensitive.
    """

    states = []
    for bsf in 'bsf':
        for lmr in 'lmr':
            states.append(lmr+bsf)

    if isinstance(x, int):
        if x > 57 or x < 0:
            raise Exception("OLL code is %d, not in [1, 57]."%x)
        code = OLL_STD_CODES[x]
        for i in range(9):
            states[i] = states[i] + code[i]
    elif isinstance(x, str) and len(x) == 9:
        for i in range(9):
            states[i] = states[i] + x[i]
    elif isinstance(x, list):
        states = x
    else:
        raise Exception('Invalid OLL state code "%s".'%str(x))
        
    if rotate not in [-270, -180, -90, 0, 90, 180, 270]:
        raise Exception('Invalid angle: "%s".'%str(rotate))

    rect_str = ''
    for state in states:
        rect_coord = op.rect_top_coord(state)
        rect_str = rect_str + svg.element('rect', id=state, x=rect_coord[0], y=rect_coord[1], width=rect_coord[2], height=rect_coord[3], rotate=rotate)

    
    with open(filename, 'w') as f:
        f.write(op.SVG_HEAD)
        f.write(op.SVG_BG)
        f.write(op.GRID_STR)
        f.write(rect_str)
        f.write(svg.TAIL)
Beispiel #5
0
    def _create_key_shapes( self ):

        shapes = svg.element( 'g', { 'class' : 'key_shapes' } )

        for ( index, shape ) in enumerate( _key_shapes ):
            shapes.append_child(
                svg.element(
                    'g',
                    {
                        'id' : ( 'key_%d' % index )
                    },
                    _make_key_paths(
                        ( shape[ 0 ] * self.xscale ),
                        ( shape[ 1 ] * self.yscale ),
                        self.radius
                    )
                )
            )

        return shapes
Beispiel #6
0
    def _create_layout( self ):

        # generate a group of key display groups
        keyboard = svg.element( 'g', { 'class' : 'layout' } )

        # iterate through each key requested for rendering
        for k in self.keys:

            # add its SVG representation to the layout
            keyboard.append_child(
                k.create_svg( self.xscale, self.yscale, self.radius )
            )

        # return the constructed layout
        return keyboard
Beispiel #7
0
def grid_path():
    '''
        Generates a 'path' element of the U face grid.
    '''

    grid_d = square_d(GRID_UL, GRID_UL,
                      GRID_STROKE_WIDTH * 4 + GRID_PATCH_SIZE * 3)
    for i in range(3):
        for j in range(3):
            x = GRID_UL + GRID_STROKE_WIDTH + i * (GRID_PATCH_SIZE +
                                                   GRID_STROKE_WIDTH)
            y = GRID_UL + GRID_STROKE_WIDTH + j * (GRID_PATCH_SIZE +
                                                   GRID_STROKE_WIDTH)
            grid_d.extend(square_d(x, y, GRID_PATCH_SIZE, anticlockwise=True))
    return svg.element('path', id="grid", d=grid_d)
Beispiel #8
0
def pll(x, rotate=0, filename="pll.svg"):
    """
        Generates PLL images.  
        
        x: state code, 1~21.

        rotate: rotation angle, clockwise, in [-270, -180, -90, 0, 90, 180, 270].  

        filename: SVG filename.
    """

    arrow_str = ''
    arrows = ''
    if isinstance(x, int):
        if x > 21 or x < 0:
            raise Exception("PLL code is %d, not in [1, 21]." % x)
        arrows = PLL_STD_CODES[x][1:]
    else:
        raise Exception('Invalid PLL state code "%s".' % str(x))

    if rotate not in [-270, -180, -90, 0, 90, 180, 270]:
        raise Exception('Invalid angle: "%s".' % str(rotate))

    for arrow in arrows:
        arrow_str += arrow_path(arrow[0], arrow[1], arrow[2], arrow[3], rotate)

    rect_str = ''
    for rect in PLL_STD_CODES[x][0]:
        rect_coord = op.rect_top_coord(rect)
        rect_str = rect_str + svg.element('rect',
                                          id=rect,
                                          x=rect_coord[0],
                                          y=rect_coord[1],
                                          width=rect_coord[2],
                                          height=rect_coord[3],
                                          rotate=rotate)

    with open(filename, 'w') as f:
        f.write(op.SVG_HEAD)
        f.write(op.SVG_BG)
        f.write(arrow_str)
        f.write(rect_str)
        f.write(op.GRID_STR)
        f.write(svg.TAIL)
Beispiel #9
0
def grid_path():
    '''
        Generates the grid in F2L
    '''
    grid_str = ''
    for fc, fcpoints in FACES_AND_CUTS.items():
        pathd = [
            'M',
        ]
        for p in fcpoints:
            coord = get_coord(p)
            pathd.append(coord.x)
            pathd.append(coord.y)
        grid_str += svg.element('path',
                                id=fc,
                                d=pathd,
                                fill='none',
                                stroke="#000000",
                                stroke_width="2")
    return grid_str
Beispiel #10
0
def f2l(x, basestate='slot', filename='f2l.svg'):
    '''
        Generates F2L SVG.

        x: F2L number, or a dict containing 'u1', 'u2', 'u3', ..., 'r9' items specifying the colours of each visible patch. For example {'f6':'r', 'f9':'b', 'r4':'b', 'r7':'r'} (if based on 'slot', =F2l 1).

        basestate: the default state of the cube, 'u' = all gray, 'w' = all white, 'cross' = cross solved, 'f2l' = F2L solved, 'oll' = OLL solved, 'complete' = all complete, default 'slot', F2L except RF slot solved.
    '''

    patches_str = ''
    if isinstance(x, int):
        if x > 41 or x < 0:
            raise Exception("F2L code is %d, not in [1, 41]." % x)
        patches = F2L_STD_CODES[x]
    elif isinstance(x, dict):
        patches = x
    else:
        raise Exception('Invalid F2L state code "%s".' % str(x))

    for patch in PATCHES.keys():
        if patch in patches:
            colour = patches[patch]
        else:
            colour = BASESTATES[basestate][patch]
        patches_str += patch_path(patch, colour)

    with open(filename, 'w') as f:
        f.write(svg.head(256, 256, 256, 256))
        f.write(
            svg.element('rect',
                        id='bg',
                        width="256",
                        height="256",
                        fill="#ffffff"))
        f.write(patches_str)
        f.write(grid_path())
        f.write(svg.TAIL)
Beispiel #11
0
def arrow_path(x, double=False, scale=1, offset=0, rotate=0):
    """
        x: 2 char string. Specifying the start and the end of the arrow in numeric codes:

         ---
        |123|
        |456|
        |789|
         ---

        double: arrow is bi-directional if true.

        scale: factor the arrow is scaled.

        offset: distance the arrow moved outside from the standard position.

        rotate: rotation angle
        
        output: svg_str of arrow(s)
    """

    corner_straight_cw = ('71', '13', '39', '97')
    corner_straight_acw = ('93', '79', '17', '31')
    edge_straight = ('82', '46', '28', '64')
    corner_slant = ('91', '73', '19', '37')
    edge_slant_cw = ('42', '26', '68', '84')
    edge_slant_acw = ('62', '86', '48', '24')

    corner_straight_x = 125 - offset
    corner_straight_y = 85
    corner_straight_len = 280 + offset

    edge_straight_x = 570 // 2
    edge_straight_y = 85 - offset
    edge_straight_len = 270

    corner_slant_x = 100 - offset
    corner_slant_y = corner_slant_x
    corner_slant_len = 410 + offset * 1.4

    edge_slant_y = 100 - offset
    edge_slant_len = 175

    if x in corner_straight_cw:
        spikex = corner_straight_x
        spikey = corner_straight_y
        arrow_len = corner_straight_len
        rotate_arrow = 90 * corner_straight_cw.index(x) + rotate

    elif x in corner_straight_acw:
        spikex = 570 - corner_straight_x
        spikey = corner_straight_y
        arrow_len = corner_straight_len
        rotate_arrow = 90 * corner_straight_acw.index(x) + rotate

    elif x in edge_straight:
        spikex = edge_straight_x
        spikey = edge_straight_y
        arrow_len = edge_straight_len
        rotate_arrow = 90 * edge_straight.index(x) + rotate

    elif x in corner_slant:
        spikex = corner_slant_x
        spikey = corner_slant_y
        arrow_len = corner_slant_len
        rotate_arrow = (90 * corner_slant.index(x) + rotate, 285, 285, -45,
                        spikex, spikey)

    elif x in edge_slant_cw:
        spikey = edge_slant_y
        spikex = 360 + 50 - edge_slant_y
        arrow_len = edge_slant_len
        rotate_arrow = (90 * edge_slant_cw.index(x) + rotate, 285, 285, 45,
                        spikex, spikey)

    elif x in edge_slant_acw:
        spikey = edge_slant_y
        spikex = 210 - 50 + edge_slant_y
        arrow_len = edge_slant_len
        rotate_arrow = (90 * edge_slant_acw.index(x) + rotate, 285, 285, -45,
                        spikex, spikey)

    else:
        raise Exception("Invalid arrow code.")

    res = svg.element('path',
                      id=x,
                      d=arrow_d(spikex, spikey, arrow_len, scale),
                      rotate=rotate_arrow)

    if double == True:
        res += arrow_path(x[1] + x[0], False, scale, offset, rotate)

    return res
Beispiel #12
0
    def create_svg( self, xscale = 42.0, yscale = 42.0, radius = 4 ):

        # determine position in the layout
        xpos = self[ 'offset' ] * xscale
        ypos = _row_offsets[ self[ 'row' ] ] * yscale

        # set the transform attribute for the group to position the key
        self.attributes[ 'transform' ] = \
            'translate(%s)' % svg.format_coord( xpos, ypos )

        # create a group to display the key
        group = svg.element( 'g', self.attributes )

        # create a use element to "clone" the appropriate shape
        group.append_child(
            svg.element(
                'use',
                { 'xlink:href' : ( '#key_%d' % self[ 'shape' ] ) }
            )
        )

        # create a sub-group to contain/limit descendents
        subgroup = svg.element(
            'g',
            { 'clip-path' : ( 'url(#clip_%d)' % self[ 'shape' ] ) }
        )

        # find the height of this key
        height = _key_shapes[ self[ 'shape' ] ][ 1 ] * yscale

        # determine text baseline position values
        edge  = radius / 2.0
        xpad  = svg.format_value( edge + 1 )
        y0pad = svg.format_value( height - ( edge + 2 ) )
        y1pad = svg.format_value( ( height / 2.0 ) - ( edge + 1 ) )

        # see if the user wants to see the default label
        if ( self.flags & key.LABEL ) == key.LABEL:

            # create and position the key label
            subgroup.append_child(
                svg.element(
                    'text',
                    { 'x' : xpad, 'y' : y0pad },
                    xml.sax.saxutils.escape( self[ 'label' ] )
                )
            )

        # see if the user wants to see the shift label (if it exists)
        if ( self[ 'shift' ] is not None ) \
            and ( ( self.flags & key.SHIFT ) == key.SHIFT ):

            # create and position the shift label
            subgroup.append_child(
                svg.element(
                    'text',
                    { 'x' : xpad, 'y' : y1pad },
                    xml.sax.saxutils.escape( self[ 'shift' ] )
                )
            )

        # display any other labels
        for label in self.labels:

            # create and position this label
            subgroup.append_child(
                svg.element(
                    'text',
                    {
                        'x' : svg.format_value( label[ 'x' ] ),
                        'y' : svg.format_value( label[ 'y' ] )
                    },
                    xml.sax.saxutils.escape( label[ 'text' ] )
                )
            )

        # append the container group
        group.append_child( subgroup )

        # return the group element
        return group
Beispiel #13
0
        h = 'v'
        v = 'h'
    return ['M', x, y, h, a, v, a, h, -a, v, -a, 'z']


def grid_path():
    '''
        Generates a 'path' element of the U face grid.
    '''

    grid_d = square_d(GRID_UL, GRID_UL,
                      GRID_STROKE_WIDTH * 4 + GRID_PATCH_SIZE * 3)
    for i in range(3):
        for j in range(3):
            x = GRID_UL + GRID_STROKE_WIDTH + i * (GRID_PATCH_SIZE +
                                                   GRID_STROKE_WIDTH)
            y = GRID_UL + GRID_STROKE_WIDTH + j * (GRID_PATCH_SIZE +
                                                   GRID_STROKE_WIDTH)
            grid_d.extend(square_d(x, y, GRID_PATCH_SIZE, anticlockwise=True))
    return svg.element('path', id="grid", d=grid_d)


GRID_STR = grid_path()

SVG_HEAD = svg.head(SVG_SIZE, SVG_SIZE, VIEWBOX_SIZE, VIEWBOX_SIZE)

SVG_BG = svg.element('rect',
                     id="bg",
                     width=VIEWBOX_SIZE,
                     height=VIEWBOX_SIZE,
                     fill="#ffffff")