File: mockgeo.py

package info (click to toggle)
thuban 1.2.2-3
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 7,752 kB
  • sloc: python: 30,427; ansic: 6,181; xml: 4,127; cpp: 1,595; makefile: 166
file content (152 lines) | stat: -rw-r--r-- 4,411 bytes parent folder | download | duplicates (6)
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
143
144
145
146
147
148
149
150
151
152
# Copyright (C) 2003 by Intevation GmbH
# Authors:
# Bernhard Herzog <bh@intevation.de>
#
# This program is free software under the GPL (>=v2)
# Read the file COPYING coming with the software for details.

"""Mock geometric/geographic objects"""

from __future__ import generators

__version__ = "$Revision: 1593 $"
# $Source$
# $Id: mockgeo.py 1593 2003-08-15 14:10:27Z bh $


class SimpleShape:

    def __init__(self, shapeid, points):
        self.shapeid = shapeid
        self.points = points

    def Points(self):
        return self.points

    def ShapeID(self):
        return self.shapeid

    def RawData(self):
        return self.points

    def compute_bbox(self):
        xs = []
        ys = []
        for part in self.Points():
            for x, y in part:
                xs.append(x)
                ys.append(y)
        return (min(xs), min(ys), max(xs), max(ys))


class SimpleShapeStore:

    """A simple shapestore object which holds its data in memory"""

    def __init__(self, shapetype, shapes, table):
        """Initialize the simple shapestore object.

        The shapetype should be one of the predefined SHAPETYPE_*
        constants. shapes is a list of shape definitions. Each
        definitions is a list of lists of tuples as returned by the
        Shape's Points() method. The table argument should be an object
        implementing the table interface and contain with one row for
        each shape.
        """
        self.shapetype = shapetype
        self.shapes = shapes
        self.table = table
        assert table.NumRows() == len(shapes)

    def ShapeType(self):
        return self.shapetype

    def Table(self):
        return self.table

    def NumShapes(self):
        return len(self.shapes)

    def Shape(self, index):
        return SimpleShape(index, self.shapes[index])

    def BoundingBox(self):
        xs = []
        ys = []
        for shape in self.shapes:
            for part in shape:
                for x, y in part:
                    xs.append(x)
                    ys.append(y)
        return (min(xs), min(ys), max(xs), max(ys))

    def ShapesInRegion(self, bbox):
        left, bottom, right, top = bbox
        if left > right:
            left, right = right, left
        if bottom > top:
            bottom, top = top, bottom
        for i in xrange(len(self.shapes)):
            shape = SimpleShape(i, self.shapes[i])
            sleft, sbottom, sright, stop = shape.compute_bbox()
            if (left <= sright and right >= sleft
                and top >= sbottom and bottom <= stop):
                yield shape

    def AllShapes(self):
        for i in xrange(len(self.shapes)):
            yield SimpleShape(i, self.shapes[i])


class AffineProjection:

    """Projection-like object implemented with an affine transformation

    The transformation matrix is defined by a list of six floats:

           [m11, m21, m12, m22, v1, v2]

    This list is essentially in the same form as used in PostScript.

    This interpreted as the following transformation of (x, y):

            / x \   / m11 m12 \ / x \   / v1 \
        T * |   | = |         | |   | + |    |
            \ y /   \ m21 m22 / \ y /   \ v2 /

    or, in homogeneous coordinates:

                     / m11 m12 v1 \ / x \
                     |            | |   |
                  ^= | m21 m22 v2 | | y |
                     |            | |   |
                     \ 0   0   1  / \ 1 /

    Obviously this is not a real geographic projection, but it's useful
    in test cases because it's simple and the result is easily computed
    in advance.
    """

    def __init__(self, coeff):
        self.coeff = coeff

        # determine the inverse transformation right away. We trust that
        # an inverse exist for the transformations used in the Thuban
        # test suite.
        m11, m21, m12, m22, v1, v2 = coeff
        det = float(m11 * m22 - m12 * m21)
        n11 = m22 / det
        n12 = -m12 / det
        n21 = -m21 / det
        n22 = m11 / det
        self.inv = [n11, n21, n12, n22, -n11*v1 - n12*v2, -n21*v1 - n22*v2]

    def _apply(self, matrix, x, y):
        m11, m21, m12, m22, v1, v2 = matrix
        return (m11 * x + m12 * y + v1), (m21 * x + m22 * y + v2)

    def Forward(self, x, y):
        return self._apply(self.coeff, x, y)

    def Inverse(self, x, y):
        return self._apply(self.inv, x, y)