-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathAddingProjections.txt
79 lines (61 loc) · 3.38 KB
/
AddingProjections.txt
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
How to add projections to the Geodetics library
===============================================
The most useful thing you can do to help the Geodetics library is to
add new projections:
New projection types
---------------------
A projection type is a generic mapping of an ellipsoid to a
plane. The library already contains the Stereographic and
Transverse Mercator projections. To add a new projection type:
* Create a new module under Geodetics to contain your projection.
* Define your new projection as a data type containing whatever
parameters your projection needs to define it. If your projection
includes a False Origin (most do) then use the GridOffset type. A
scaling factor should be a Dimensionless Double.
If the projection has intermediate values derived purely from these
parameters then you can make it more efficient if you include them
in the data type rather than recalculating them every time. If you
do this then don't export the constructor, and have a separate
function to fill out the data structure correctly. See Stereographic
for an example.
* Make your new projection an instance of GridClass and define the
"toGrid", "fromGrid" and "gridEllipsoid" functions. Generic grids
should have the ellipsoid as a parameter.
National and other standard projections
---------------------------------------
A standard projection is a distinguished value of a generic
projection. For instance the UK National Grid is a value of the
TransverseMercator projection.
A standard projection should be based on a generic projection. There
is little point in duplicating code for two standard projections if
they are based on the same underlying mathematics. Therefore the
design for a standard projection contains the following elements:
* A representation of the projection as an untyped value of the
underlying generic projection. For instance the UK OS grid is
represented by "ukGrid :: GridTM OSGB36".
* A unit type (that is, one constructor with no arguments) that is an
instance of the GridClass. Implement the "toGrid" and "fromGrid"
functions using the "unsafeGridCoerce" function and the untyped
value defined above. For instace the UkNationalGrid type has the
following implementations in its GridClass instance:
toGrid _ = unsafeGridCoerce UkNationalGrid . toGrid ukGrid
fromGrid = fromGrid . unsafeGridCoerce ukGrid
If your standard projection has a particular ellipsoid that is not
already defined (for instance, the UK national grid is based on
OSGB36) then this should be defined as a unit type in the same module
and made an instance of Ellipsoid.
If there is a grid reference system associated with the projection
then this should be implemented as a pair of functions between strings
and gridpoints. When converting from a string make sure that some part
of the result indicates the precision of the reference. One way is to
return a gridpoint for the southwest corner of the grid square and an
offset to the centre.
Testing
-------
In the "test" folder create a new module for your projection and
import it into "Main.hs". All projections should have several test
points derived from a known oracle (such as a pre-existing
implementation or reference table). Cite the source in a comment to
your test data. In addition generic projections should have a "round
trip" test using QuickCheck to show that (fromGrid . toGrid) is an
identity to within some specified accuracy.