Skip to content

Commit 3e9ba09

Browse files
committed
Merge pull request #8 from SamMousa/master
Added Proj4Config and Proj4Importer objects.
2 parents 3312025 + c5eb55f commit 3e9ba09

12 files changed

+1608
-96
lines changed

Diff for: src/AbstractProjection.php

+2-93
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@
55
* CHECKME: The projection - is it a point? Or is it something that a projected point inherits?
66
*/
77

8+
use Academe\Proj\Traits\ProjectionTrait;
89
use Exception;
910
use Academe\Proj\Point\Geodetic;
1011
use Academe\Proj\ProjectionInterface;
1112

1213
abstract class AbstractProjection implements ProjectionInterface
1314
{
15+
use ProjectionTrait;
1416
// M_PI*2
15-
const TWO_PI = 6.283185307179586477;
1617

1718
const EPSLN = 1.0e-10;
1819

@@ -122,97 +123,5 @@ public function asArray()
122123
return $this->params;
123124
}
124125

125-
/**
126-
* Utility methods used by many of the forward/inverse conversions.
127-
*/
128-
129-
/**
130-
* Adjust longitude to -PI to +PI (-180 to +180 degrees); input in radians.
131-
*/
132-
protected function adjustLon($lon)
133-
{
134-
return (abs($lon) < M_PI) ? $lon : ($lon - ($this->sign($lon) * static::TWO_PI));
135-
}
136-
137-
/**
138-
* Adjust latitude to -PI/2 to +PI/2 (-90 to +90 degrees); input in radians.
139-
*/
140-
protected function adjustLat($lat)
141-
{
142-
return (abs($lat) < M_PI_2) ? $lat : ($lat - ($this->sign($lat) * M_PI));
143-
}
144-
145-
protected function sign($num)
146-
{
147-
return $num < 0.0 ? -1 : 1;
148-
}
149-
150-
/**
151-
* following functions from gctpc cproj.c for transverse mercator projections
152-
*
153-
* @param type $x == es == essentricity squared
154-
* @return type
155-
*/
156-
protected function e0fn($x)
157-
{
158-
return (1.0 - ($x / 4.0) * (1.0 + $x / 16.0 * (3.0 + 1.25 * $x)));
159-
}
160-
161-
/**
162-
* @param type $x
163-
* @return type
164-
*/
165-
protected function e1fn($x)
166-
{
167-
return (0.375 * $x * (1.0 + 0.25 * $x * (1.0 + 0.46875 * $x)));
168-
}
169126

170-
/**
171-
* @param type $x
172-
* @return type
173-
*/
174-
protected function e2fn($x)
175-
{
176-
return (0.05859375 * $x * $x * (1.0 + 0.75 * $x));
177-
}
178-
179-
/**
180-
* @param type $x
181-
* @return type
182-
*/
183-
protected function e3fn($x)
184-
{
185-
return ($x * $x * $x * (35.0 / 3072.0));
186-
}
187-
188-
/**
189-
* Function to eliminate roundoff errors in asin
190-
*
191-
* @param type $x
192-
* @return type
193-
*/
194-
protected function asinz($x)
195-
{
196-
return asin(
197-
abs($x) > 1.0 ? ($x > 1.0 ? 1.0 : -1.0) : $x
198-
);
199-
200-
//if( abs( $x ) > 1.0 ) {
201-
// $x = ($x > 1.0) ? 1.0 : -1.0;
202-
//}
203-
//return asin( $x );
204-
}
205-
206-
/**
207-
* @param type $e0
208-
* @param type $e1
209-
* @param type $e2
210-
* @param type $e3
211-
* @param type $phi
212-
* @return type
213-
*/
214-
protected function mlfn($e0, $e1, $e2, $e3, $phi)
215-
{
216-
return ($e0 * $phi - $e1 * sin(2.0 * $phi) + $e2 * sin(4.0 * $phi) - $e3 * sin(6.0 * $phi));
217-
}
218127
}

Diff for: src/Datum.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ class Datum
8686
/**
8787
* A datum needs parameters to be defined.
8888
* These will be three parameters offering a spacial shift, or seven
89-
* parameters offering a spacial shift + reotations + scale.
89+
* parameters offering a spacial shift + rotations + scale.
9090
* Parameters can be left empty, in which case the datum defaults to
9191
* WGS84 (which is the reference datum, so no transformations are needed).
9292
* of points. Except - is the ellipse carried by the datum or the point? I think

Diff for: src/Proj4Config.php

+268
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,268 @@
1+
<?php
2+
3+
4+
namespace Academe\Proj;
5+
6+
/**
7+
* This class parses and holds a Proj4 configuration.
8+
* @package Academe\Proj
9+
*/
10+
class Proj4Config
11+
{
12+
/**
13+
* @var string The source string that this object was constructed from.
14+
*/
15+
private $source;
16+
17+
/**
18+
* @var Semimajor radius of the ellipsoid axis
19+
*/
20+
protected $a;
21+
22+
/**
23+
* @var ? Used with Oblique Mercator and possibly a few others
24+
*/
25+
protected $alpha;
26+
27+
/**
28+
* @var Axis orientation (new in 4.8.0)
29+
*/
30+
protected $axis;
31+
32+
/**
33+
* @var Semiminor radius of the ellipsoid axis
34+
*/
35+
protected $b;
36+
37+
/**
38+
* @var stringDatum name (see `proj -ld`)
39+
*/
40+
protected $datum;
41+
42+
/**
43+
* @var string Ellipsoid name (see `proj -le`)
44+
*/
45+
protected $ellps = 'WGS84';
46+
47+
/**
48+
* @var float Scaling factor (old name)
49+
*/
50+
protected $k;
51+
52+
/**
53+
* @var float Scaling factor (new name)
54+
*/
55+
protected $k_0;
56+
57+
/**
58+
* @var float Latitude of origin
59+
*/
60+
protected$lat_0;
61+
62+
/**
63+
* @var float Latitude of first standard parallel
64+
*/
65+
protected $lat_1;
66+
67+
/**
68+
* @var float Latitude of second standard parallel
69+
*/
70+
protected $lat_2;
71+
72+
/**
73+
* @var float Latitude of true scale
74+
*/
75+
protected $lat_ts;
76+
77+
/**
78+
* @var float Central meridian
79+
*/
80+
protected $lon_0;
81+
82+
/**
83+
* @var ? Longitude used with Oblique Mercator and possibly a few others
84+
*/
85+
protected $lonc;
86+
87+
/**
88+
* @var Center longitude to use for wrapping (see below)
89+
*/
90+
protected $lon_wrap;
91+
92+
/**
93+
* @var Filename of NTv2 grid file to use for datum transforms (see below)
94+
*/
95+
protected $nadgrids;
96+
97+
/**
98+
* @var Don't use the /usr/share/proj/proj_def.dat defaults file
99+
*/
100+
protected $no_defs;
101+
102+
/**
103+
* @var Allow longitude output outside -180 to 180 range, disables wrapping (see below)
104+
*/
105+
protected $over;
106+
107+
/**
108+
* @var string Alternate prime meridian (typically a city name, see below)
109+
*/
110+
protected $pm;
111+
112+
/**
113+
* @var string Projection name (see `proj -l`)
114+
*/
115+
protected $proj;
116+
/**
117+
* @var Denotes southern hemisphere UTM zone
118+
*/
119+
protected $south;
120+
121+
/**
122+
* @var float Multiplier to convert map units to 1.0m
123+
*/
124+
protected $to_meter;
125+
126+
/**
127+
* @var 3 or 7 term datum transform parameters (see below)
128+
*/
129+
protected $towgs84;
130+
131+
/**
132+
* @var meters, US survey feet, etc.
133+
*/
134+
protected $units;
135+
136+
/**
137+
* @var vertical conversion to meters.
138+
*/
139+
protected $vto_meter;
140+
141+
/**
142+
* @var vertical units.
143+
*/
144+
protected $vunits;
145+
146+
/**
147+
* @var int False easting
148+
*/
149+
protected $x_0;
150+
151+
/**
152+
* @var int False northing
153+
*/
154+
protected $y_0;
155+
156+
/**
157+
* @var UTM zone
158+
*/
159+
protected $zone;
160+
161+
/**
162+
* @var string Title of this definition.
163+
*/
164+
protected $title;
165+
166+
/**
167+
* @var float
168+
*/
169+
protected $from_greenwich = 0.0;
170+
171+
public function __construct($configurationString)
172+
{
173+
$this->source = $configurationString;
174+
$params = $this->parseIntoArray($configurationString);
175+
foreach($params as $key => $value) {
176+
$attribute = lcfirst($key);
177+
$setter = 'set' . ucfirst($attribute);
178+
if (method_exists($this, $setter)) {
179+
$this->$setter($value);
180+
} elseif (property_exists($this, $attribute)) {
181+
$this->$attribute = $value;
182+
} else {
183+
throw new \Exception("Unknown parameter: '$key' for definition: $configurationString");
184+
}
185+
}
186+
187+
}
188+
189+
/**
190+
* Static because it does not need $this, public because someone might want to use it outside the context
191+
* of creating an instance of this class.
192+
* @param $string
193+
*/
194+
public static function parseIntoArray($string)
195+
{
196+
preg_match_all('/\+(?<key>\w+)=(?<val>.*?)(?:\+|$)/', $string, $matches);
197+
$result = [];
198+
foreach($matches['key'] as $i => $key) {
199+
$result[$key] = self::convert($matches['val'][$i], $key);
200+
201+
}
202+
return $result;
203+
}
204+
205+
/**
206+
* This converts PROJ4 values to native PHP values.
207+
* The goal is to be flexible and speed is not a primary concern (at this point).
208+
* @param string $value
209+
* @param $key Optional key to help with deciding the format.
210+
* @return float|null|int|string
211+
*/
212+
public static function convert($value, $key = null)
213+
{
214+
$value = trim($value);
215+
if (strpos($value, '/') !== false
216+
&& count($parts = explode('/', $value)) === 2
217+
&& is_numeric($parts[0])
218+
&& is_numeric($parts[1])
219+
) {
220+
return floatval($parts[0]) / floatval($parts[1]);
221+
} elseif (ctype_digit($value)) {
222+
return intval($value);
223+
} elseif (is_numeric($value)) {
224+
return floatval($value);
225+
} elseif (empty($value)) {
226+
return null;
227+
} elseif (preg_match('/^(-?[0-9]+(\.[0-9]*)?)(,(-?[0-9]+(\.[0-9]*)?))*$/', $value, $matches)) {
228+
return array_map('self::convert', explode(',', $value));
229+
} elseif (preg_match('/^(?<k>[a-zA-Z\d]*?)=(?<v>.*?)$/', $value, $matches)) {
230+
return [
231+
$matches['k'] => self::convert($matches['v'], $matches['k'])
232+
];
233+
} else {
234+
// echo "Can't convert: $value\n";
235+
236+
}
237+
return $value;
238+
}
239+
240+
/**
241+
* @return Ellipsoid
242+
*/
243+
public function getEllipsoid()
244+
{
245+
// This is just to show it is working, obviously it needs refactoring to load this in a more centralized matter.
246+
$definitions = json_decode(file_get_contents(__DIR__ . '/data/ellipsoids.json'), true);
247+
if (isset($definitions[$this->ellps])) {
248+
return new Ellipsoid($definitions[$this->ellps]);
249+
} else {
250+
throw new \Exception("Can't find definition for ellipsoid: $this->ellps");
251+
}
252+
253+
}
254+
255+
/**
256+
* @return Datum
257+
*/
258+
public function getDatum()
259+
{
260+
if (!isset($this->towgs84)) {
261+
// These 3 are translation parameters, 0 is an identity for translation.
262+
return new Datum([0, 0, 0], $this->getEllipsoid());
263+
} else {
264+
return new Datum($this->towgs84, $this->getEllipsoid());
265+
}
266+
}
267+
268+
}

0 commit comments

Comments
 (0)