|
1 # |
|
2 # Copyright (c) 2008-2017 Thierry Florac <tflorac AT ulthar.net> |
|
3 # All Rights Reserved. |
|
4 # |
|
5 # This software is subject to the provisions of the Zope Public License, |
|
6 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. |
|
7 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED |
|
8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS |
|
10 # FOR A PARTICULAR PURPOSE. |
|
11 # |
|
12 |
|
13 __docformat__ = 'restructuredtext' |
|
14 |
|
15 |
|
16 # import standard library |
|
17 |
|
18 # import interfaces |
|
19 |
|
20 # import packages |
|
21 from pyams_utils.schema import DottedDecimalField |
|
22 from zope.interface import invariant, Interface, Invalid, Attribute |
|
23 from zope.schema import Choice |
|
24 from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm |
|
25 |
|
26 from pyams_gis import _ |
|
27 |
|
28 |
|
29 WGS84 = 4326 |
|
30 WGS84WM = 3857 |
|
31 RGF93 = 2154 |
|
32 LAMBERT_IIE = 27572 |
|
33 UTM_20N = 4559 |
|
34 UTM_22N = 2972 |
|
35 UTM_38S = 4471 |
|
36 UTM_40S = 2975 |
|
37 |
|
38 COORDINATES_PROJECTIONS = {WGS84: _("WGS84 (GPS)"), |
|
39 WGS84WM: _("WGS84 Web Mercator"), |
|
40 RGF93: _("Lambert 93 (Metropolitan France)"), |
|
41 LAMBERT_IIE: _("Extended Lambert II (Metropolitan France)"), |
|
42 UTM_20N: _("UTM Zone 20N (Martinique, Guadeloupe)"), |
|
43 UTM_22N: _("UTM Zone 22N (Guyane)"), |
|
44 UTM_38S: _("UTM Zone 38S (Mayotte)"), |
|
45 UTM_40S: _("UTM Zone 40S (La RĂ©union)")} |
|
46 |
|
47 COORDINATES_PROJECTION_VOCABULARY = SimpleVocabulary(sorted([SimpleTerm(v, title=t) |
|
48 for v, t in COORDINATES_PROJECTIONS.items()], |
|
49 key=lambda x: x.title)) |
|
50 |
|
51 LAYER_CRS = {WGS84: 'L.CRS.EPSG4326', |
|
52 WGS84WM: 'L.CRS.EPSG3857', |
|
53 RGF93: 'L.geoportalCRS.EPSG2154', |
|
54 LAMBERT_IIE: 'L.geoportalCRS.EPSG27572'} |
|
55 |
|
56 LAYER_CRS_VOCABULARY = SimpleVocabulary([SimpleTerm(t, title=COORDINATES_PROJECTIONS[v]) |
|
57 for v, t in LAYER_CRS.items()]) |
|
58 |
|
59 |
|
60 class IGeoPoint(Interface): |
|
61 """GeoPoint attribute interface""" |
|
62 |
|
63 longitude = DottedDecimalField(title=_("Longitude"), |
|
64 required=False) |
|
65 |
|
66 latitude = DottedDecimalField(title=_("Latitude"), |
|
67 required=False) |
|
68 |
|
69 projection = Choice(title=_("Projection system"), |
|
70 vocabulary=COORDINATES_PROJECTION_VOCABULARY, |
|
71 default=WGS84, |
|
72 required=False) |
|
73 |
|
74 @invariant |
|
75 def check_coordinates(self): |
|
76 data = set(map(bool, (self.longitude, self.latitude))) |
|
77 if len(data) == 2: |
|
78 raise Invalid(_("You must set longitude and latitude, or None!")) |
|
79 if self.longitude and not self.projection: |
|
80 raise Invalid(_("You can't set coordinates without setting projection!")) |
|
81 |
|
82 def get_coordinates(self, projection=WGS84): |
|
83 """Get coordinates translated to given projection""" |
|
84 |
|
85 wgs_coordinates = Attribute("Coordinates tuple in WGS84 projection") |
|
86 |
|
87 |
|
88 class IGeoPointZ(IGeoPoint): |
|
89 """GeoPointZ attribute interface""" |
|
90 |
|
91 altitude = DottedDecimalField(title=_("Altitude"), |
|
92 required=False) |
|
93 |
|
94 |
|
95 class IGeoArea(Interface): |
|
96 """Geographic area defined by a rectangle""" |
|
97 |
|
98 x1 = DottedDecimalField(title=_("West limit"), |
|
99 required=False) |
|
100 |
|
101 y1 = DottedDecimalField(title=_("South limit"), |
|
102 required=False) |
|
103 |
|
104 x2 = DottedDecimalField(title=_("East limit"), |
|
105 required=False) |
|
106 |
|
107 y2 = DottedDecimalField(title=_("North limit"), |
|
108 required=False) |
|
109 |
|
110 projection = Choice(title=_("Projection system"), |
|
111 vocabulary=COORDINATES_PROJECTION_VOCABULARY, |
|
112 default=WGS84, |
|
113 required=False) |
|
114 |
|
115 @invariant |
|
116 def check_coordinates(self): |
|
117 data = set(map(bool, (self.x1, self.x2, self.y1, self.y2))) |
|
118 if len(data) == 2: |
|
119 raise Invalid(_("You must set all coordinates or None!")) |
|
120 if self.x1 and not self.projection: |
|
121 raise Invalid(_("You can't set coordinates without setting projection!")) |
|
122 |
|
123 def get_coordinates(self, projection=WGS84): |
|
124 """Get coordinates translated to given projection""" |
|
125 |
|
126 wgs_coordinates = Attribute("Coordinates in WGS84 projection") |