File: agg_segment_collection.py

package info (click to toggle)
python-vispy 0.15.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 8,868 kB
  • sloc: python: 59,799; javascript: 6,800; makefile: 69; sh: 6
file content (142 lines) | stat: -rw-r--r-- 4,710 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# -*- coding: utf-8 -*-
# -----------------------------------------------------------------------------
# Copyright (c) 2014, Nicolas P. Rougier
# Distributed under the (new) BSD License. See LICENSE.txt for more info.
# -----------------------------------------------------------------------------
"""
Antigrain Geometry Segment Collection

This collection provides antialiased and accurate segments with caps. It
consume x2 more memory than regular lines and is a bit slower, but the quality
of the output is worth the cost.
"""
import numpy as np
from ... import glsl
from . collection import Collection
from ..transforms import NullTransform


class AggSegmentCollection(Collection):
    """
    Antigrain Geometry Segment Collection

    This collection provides antialiased and accurate segments with caps. It
    consume x2 more memory than regular lines and is a bit slower, but the
    quality of the output is worth the cost.
    """

    def __init__(self, user_dtype=None, transform=None,
                 vertex=None, fragment=None, **kwargs):
        """
        Initialize the collection.

        Parameters
        ----------
        user_dtype: list
            The base dtype can be completed (appended) by the used_dtype. It
            only make sense if user also provide vertex and/or fragment shaders

        transform : string
            GLSL Transform code defining the vec4 transform(vec3) function

        vertex: string
            Vertex shader code

        fragment: string
            Fragment  shader code

        caps : string
            'local', 'shared' or 'global'

        color : string
            'local', 'shared' or 'global'

        linewidth : string
            'local', 'shared' or 'global'

        antialias : string
            'local', 'shared' or 'global'
        """
        base_dtype = [('P0', (np.float32, 3), '!local', (0, 0, 0)),
                      ('P1', (np.float32, 3), '!local', (0, 0, 0)),
                      ('index', (np.float32, 1), '!local', 0),
                      ('color', (np.float32, 4), 'shared', (0, 0, 0, 1)),
                      ('linewidth', (np.float32, 1), 'shared', 1),
                      ('antialias', (np.float32, 1), 'shared', 1),
                      ('viewport', (np.float32, 4), 'global', (0, 0, 512, 512))]  # noqa

        dtype = base_dtype
        if user_dtype:
            dtype.extend(user_dtype)

        if vertex is None:
            vertex = glsl.get('collections/agg-segment.vert')
        if transform is None:
            transform = NullTransform()
        self.transform = transform        
        if fragment is None:
            fragment = glsl.get('collections/agg-segment.frag')

        Collection.__init__(self, dtype=dtype, itype=np.uint32,
                            mode="triangles",
                            vertex=vertex, fragment=fragment, **kwargs)
        self._programs[0].vert['transform'] = self.transform

    def append(self, P0, P1, itemsize=None, **kwargs):
        """
        Append a new set of segments to the collection.

        For kwargs argument, n is the number of vertices (local) or the number
        of item (shared)

        Parameters
        ----------
        P : np.array
            Vertices positions of the path(s) to be added

        itemsize: int or None
            Size of an individual path

        caps : list, array or 2-tuple
           Path start /end cap

        color : list, array or 4-tuple
           Path color

        linewidth : list, array or float
           Path linewidth

        antialias : list, array or float
           Path antialias area
        """
        itemsize = itemsize or 1
        itemcount = len(P0) // itemsize

        V = np.empty(itemcount, dtype=self.vtype)

        # Apply default values on vertices
        for name in self.vtype.names:
            if name not in ['collection_index', 'P0', 'P1', 'index']:
                V[name] = kwargs.get(name, self._defaults[name])

        V['P0'] = P0
        V['P1'] = P1
        V = V.repeat(4, axis=0)
        V['index'] = np.resize([0, 1, 2, 3], 4 * itemcount * itemsize)

        idxs = np.ones((itemcount, 6), dtype=int)
        idxs[:] = 0, 1, 2, 0, 2, 3
        idxs[:] += 4 * np.arange(itemcount)[:, np.newaxis]
        idxs = idxs.ravel()

        # Uniforms
        if self.utype:
            U = np.zeros(itemcount, dtype=self.utype)
            for name in self.utype.names:
                if name not in ["__unused__"]:
                    U[name] = kwargs.get(name, self._defaults[name])
        else:
            U = None

        Collection.append(
            self, vertices=V, uniforms=U, indices=idxs, itemsize=4 * itemcount)