WfsGeomTypeConverter.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. <?php
  2. Lib::loadClass('Api_WfsException');
  3. class Api_WfsGeomTypeConverter {
  4. public function getType($geomType) {
  5. }
  6. public function convertGmlCoordinatesToWkt($gmlCoordinates) {
  7. $DBG = (V::get('DBG_GML_CONV', '', $_GET) > 0);// TODO: Profiler
  8. $wkt = null;
  9. if($DBG){echo "\ngmlCoordinates L." . __LINE__ . ": " . str_replace(' ', "\n", $gmlCoordinates) . "\n";}
  10. $gmlFormats = array();
  11. $gmlFormats[] = array('cs'=>',', 'ts'=>' ');// QGIS request
  12. $gmlFormats[] = array('cs'=>' ', 'ts'=>',', 'decimal'=>'.');// WKT
  13. $wktTypesMap = array();
  14. $wktTypesMap['Point'] = 'POINT';
  15. $wktTypesMap['LineString'] = 'LINESTRING';
  16. $wktTypesMap['Polygon'] = 'POLYGON';
  17. //$wktTypesMap[''] = 'MULTIPOINT';
  18. //$wktTypesMap[''] = 'MULTILINESTRING';
  19. //$wktTypesMap[''] = 'MULTIPOLYGON';
  20. /*
  21. <extension base="string">
  22. <attribute name="decimal" type="string" use="optional" default="."/>
  23. <attribute name="cs" type="string" use="optional" default=","/>
  24. <attribute name="ts" type="string" use="optional" default=" "/>
  25. </extension>
  26. */
  27. foreach ($gmlFormats as $i => $gmlFormat) {
  28. $gmlPoint = '((\-?\d+\.?\d*)' .$gmlFormat['cs'] . '(\-?\d+\.?\d*))';
  29. //$gmlPoints = $gmlPoint . '(' .$gmlFormat['ts'] . $gmlPoint . ')+';
  30. $gmlPoints = $gmlPoint . '(' .$gmlFormat['ts'] . $gmlPoint . ')*';
  31. $wktPolygonPattern = '/^([a-zA-Z]+)\(\(?' . $gmlPoints . '\)?\)$/';
  32. if($DBG){echo 'wktPolygonPattern:';print_r($wktPolygonPattern);echo "\n";}
  33. $matches = array();
  34. if (preg_match($wktPolygonPattern, $gmlCoordinates, $matches)) {
  35. if($DBG){echo "[{$i}]matches:";print_r($matches);echo "\n";}
  36. if (count($matches) > 2) {
  37. $wktType = $matches[1];
  38. if($DBG){echo 'wktType:';print_r($wktType);echo "\n";}
  39. if (!array_key_exists($wktType, $wktTypesMap)) {
  40. throw new Api_WfsException("Gml type '{$wktType}' not supported", 501);
  41. }
  42. $wkt = $gmlCoordinates;
  43. $wkt = str_replace(array($gmlFormat['cs'], $gmlFormat['ts']), array('#cs#', '#ts#'), $wkt);
  44. $wkt = str_replace(array('#cs#', '#ts#'), array(' ', ','), $wkt);
  45. $wkt = str_replace($wktType, $wktTypesMap[$wktType], $wkt);
  46. if($DBG){echo 'wkt:';print_r($wkt);echo "\n";}
  47. }
  48. break;
  49. }
  50. }
  51. if (!$wkt) {
  52. throw new Api_WfsException("Gml coordinates not supported", 501);
  53. }
  54. return $wkt;
  55. }
  56. public function createGmlFromWkt($geomAsWkt, $dom) {
  57. /* @see http://en.wikipedia.org/wiki/Geography_Markup_Language
  58. *
  59. * LineString:
  60. <gml:LineString xmlns:gml="http://www.opengis.net/gml" srsName="http://www.opengis.net/gml/srs/epsg.xml#4326">
  61. <gml:coordinates xmlns:gml="http://www.opengis.net/gml" decimal="." cs=" " ts=",">
  62. 18.5142937987997 54.3142300873962,18.5142730427068 54.3142435923024
  63. </gml:coordinates>
  64. </gml:LineString>
  65. *
  66. * Polygon:
  67. <gml:Polygon xmlns:gml="http://www.opengis.net/gml" srsName="http://www.opengis.net/gml/srs/epsg.xml#4326">
  68. <gml:outerBoundaryIs>
  69. <gml:LinearRing>
  70. <gml:coordinates xmlns:gml="http://www.opengis.net/gml" decimal="." cs=" " ts=",">18.4252094051732 54.377797436489,18.4150883433964 54.3729569286827,18.4425912286593 54.3696565824512,18.4379707439351 54.3780174595711,18.4252094051732 54.377797436489</gml:coordinates>
  71. </gml:LinearRing>
  72. </gml:outerBoundaryIs>
  73. </gml:Polygon>
  74. *
  75. * Point:
  76. <gml:Point xmlns:gml="http://www.opengis.net/gml" srsName="http://www.opengis.net/gml/srs/epsg.xml#4326">
  77. <gml:coordinates xmlns:gml="http://www.opengis.net/gml" decimal="." cs=" " ts=",">100 200</gml:coordinates>
  78. </gml:Point>
  79. *
  80. */
  81. $DBG = (V::get('DBG_GEO', '', $_GET) > 0);// TODO: Profiler
  82. if (empty($geomAsWkt)) return null;
  83. // WKT: http://en.wikipedia.org/wiki/Well-known_text
  84. if($DBG){echo 'wkt:';print_r($geomAsWkt);echo "\n";}
  85. $gmlCoordinatesFromWkt = '';
  86. $bbox = null;
  87. $bboxPolygon = null;
  88. $wktType = substr($geomAsWkt, 0, strpos($geomAsWkt, '('));
  89. $sql = "select
  90. -- GeometryType(GeomFromText('{$geomAsWkt}')) as type,
  91. AsText(Envelope(GeomFromText('{$geomAsWkt}'))) as bbox
  92. ";
  93. $db = DB::getDB();
  94. $res = $db->query($sql);
  95. if ($r = $db->fetch($res)) {
  96. $bboxPolygon = $r->bbox;
  97. }
  98. if($DBG){echo 'wktType:';print_r($wktType);echo "\n";}
  99. if($DBG){echo 'bboxPolygon:';print_r($bboxPolygon);echo "\n";}
  100. if ($bboxPolygon) {// eg. POLYGON((18.550927583884 54.3124269117497,18.6401914998997 54.3124269117497,18.6401914998997 54.3608667397837,18.550927583884 54.3608667397837,18.550927583884 54.3124269117497))
  101. $bbox = '';
  102. $wktPoint = '(\d+\.?\d*) (\d+\.?\d*)';
  103. $wktPolygonPattern = '/^POLYGON\(\(' . $wktPoint . ',' . $wktPoint . ',' . $wktPoint . ',' . $wktPoint . ',' . $wktPoint . '\)\)$/';
  104. if($DBG){echo 'wktPolygonPattern:';print_r($wktPolygonPattern);echo "\n";}
  105. if (preg_match($wktPolygonPattern, $bboxPolygon, $matches)) {
  106. $bbox = $matches;
  107. }
  108. }
  109. if($DBG){echo 'bbox:';print_r($bbox);echo "\n";}
  110. if ('POLYGON' === $wktType) {
  111. $gmlCoordinatesFromWkt = $geomAsWkt;
  112. $gmlCoordinatesFromWkt = substr($gmlCoordinatesFromWkt, strlen('POLYGON(('));
  113. $gmlCoordinatesFromWkt = substr($gmlCoordinatesFromWkt, 0, -1 * strlen('))'));
  114. $gmlType = 'Polygon';
  115. }
  116. else if ('LINESTRING' === $wktType) {
  117. $gmlCoordinatesFromWkt = $geomAsWkt;
  118. $gmlCoordinatesFromWkt = substr($gmlCoordinatesFromWkt, strlen('LINESTRING('));
  119. $gmlCoordinatesFromWkt = substr($gmlCoordinatesFromWkt, 0, -1 * strlen(')'));
  120. $gmlType = 'LineString';
  121. }
  122. else if ('POINT' === $wktType) {
  123. $gmlCoordinatesFromWkt = $geomAsWkt;
  124. $gmlCoordinatesFromWkt = substr($gmlCoordinatesFromWkt, strlen('POINT('));
  125. $gmlCoordinatesFromWkt = substr($gmlCoordinatesFromWkt, 0, -1 * strlen(')'));
  126. $gmlCoordinatesFromWkt = str_replace(' ', ',', $gmlCoordinatesFromWkt);
  127. $gmlType = 'Point';
  128. }
  129. else {
  130. return null;
  131. }
  132. if($DBG){echo 'gmlCoordinatesFromWkt:';print_r($gmlCoordinatesFromWkt);echo "\n";}
  133. $geomNode = $dom->createElementNS('http://www.opengis.net/gml', 'gml:' . $gmlType);
  134. $geomNode->setAttribute('srsName', "http://www.opengis.net/gml/srs/epsg.xml#4326");// TODO: EPSG
  135. if ('Point' === $gmlType) {
  136. $coordinatesNode = $dom->createElementNS('http://www.opengis.net/gml', 'gml:coordinates');
  137. $geomNode->appendChild($coordinatesNode);
  138. //$coordinatesNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:gml', 'http://www.opengis.net/gml');
  139. //$coordinatesNode->setAttribute('decimal', '.');
  140. //$coordinatesNode->setAttribute('cs', ' ');
  141. //$coordinatesNode->setAttribute('ts', ',');
  142. $coordinatesNode->nodeValue = $gmlCoordinatesFromWkt;
  143. } else if ('LineString' === $gmlType) {
  144. $coordinatesNode = $dom->createElementNS('http://www.opengis.net/gml', 'gml:coordinates');
  145. $geomNode->appendChild($coordinatesNode);
  146. $coordinatesNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:gml', 'http://www.opengis.net/gml');
  147. $coordinatesNode->setAttribute('decimal', '.');
  148. $coordinatesNode->setAttribute('cs', ' ');
  149. $coordinatesNode->setAttribute('ts', ',');
  150. $coordinatesNode->nodeValue = $gmlCoordinatesFromWkt;
  151. } else {
  152. $outerBoundsNode = $dom->createElementNS('http://www.opengis.net/gml', 'gml:outerBoundaryIs');
  153. $geomNode->appendChild($outerBoundsNode);
  154. $linearRingNode = $dom->createElementNS('http://www.opengis.net/gml', 'gml:LinearRing');
  155. $outerBoundsNode->appendChild($linearRingNode);
  156. $coordinatesNode = $dom->createElementNS('http://www.opengis.net/gml', 'gml:coordinates');
  157. $linearRingNode->appendChild($coordinatesNode);
  158. $coordinatesNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:gml', 'http://www.opengis.net/gml');
  159. $coordinatesNode->setAttribute('decimal', '.');
  160. $coordinatesNode->setAttribute('cs', ' ');
  161. $coordinatesNode->setAttribute('ts', ',');
  162. $coordinatesNode->nodeValue = $gmlCoordinatesFromWkt;
  163. }
  164. return $geomNode;
  165. }
  166. public function createGmlFromWkt_xmlWriter($geomAsWkt, $xmlWriter) {
  167. $DBG = (V::get('DBG_GEO', '', $_GET) > 0);// TODO: Profiler
  168. if (empty($geomAsWkt)) return null;
  169. // WKT: http://en.wikipedia.org/wiki/Well-known_text
  170. if($DBG){echo 'wkt:';print_r($geomAsWkt);echo "\n";}
  171. $gmlCoordinatesFromWkt = '';
  172. $bbox = null;
  173. $bboxPolygon = null;
  174. $wktType = substr($geomAsWkt, 0, strpos($geomAsWkt, '('));
  175. $sql = "select
  176. -- GeometryType(GeomFromText('{$geomAsWkt}')) as type,
  177. AsText(Envelope(GeomFromText('{$geomAsWkt}'))) as bbox
  178. ";
  179. $db = DB::getDB();
  180. $res = $db->query($sql);
  181. if ($r = $db->fetch($res)) {
  182. $bboxPolygon = $r->bbox;
  183. }
  184. if($DBG){echo 'wktType:';print_r($wktType);echo "\n";}
  185. if($DBG){echo 'bboxPolygon:';print_r($bboxPolygon);echo "\n";}
  186. if ($bboxPolygon) {// eg. POLYGON((18.550927583884 54.3124269117497,18.6401914998997 54.3124269117497,18.6401914998997 54.3608667397837,18.550927583884 54.3608667397837,18.550927583884 54.3124269117497))
  187. $bbox = '';
  188. $wktPoint = '(\d+\.?\d*) (\d+\.?\d*)';
  189. $wktPolygonPattern = '/^POLYGON\(\(' . $wktPoint . ',' . $wktPoint . ',' . $wktPoint . ',' . $wktPoint . ',' . $wktPoint . '\)\)$/';
  190. if($DBG){echo 'wktPolygonPattern:';print_r($wktPolygonPattern);echo "\n";}
  191. if (preg_match($wktPolygonPattern, $bboxPolygon, $matches)) {
  192. $bbox = $matches;
  193. }
  194. }
  195. if($DBG){echo 'bbox:';print_r($bbox);echo "\n";}
  196. if ('POLYGON' === $wktType) {
  197. $gmlCoordinatesFromWkt = $geomAsWkt;
  198. $gmlCoordinatesFromWkt = substr($gmlCoordinatesFromWkt, strlen('POLYGON(('));
  199. $gmlCoordinatesFromWkt = substr($gmlCoordinatesFromWkt, 0, -1 * strlen('))'));
  200. $gmlType = 'Polygon';
  201. }
  202. else if ('LINESTRING' === $wktType) {
  203. $gmlCoordinatesFromWkt = $geomAsWkt;
  204. $gmlCoordinatesFromWkt = substr($gmlCoordinatesFromWkt, strlen('LINESTRING('));
  205. $gmlCoordinatesFromWkt = substr($gmlCoordinatesFromWkt, 0, -1 * strlen(')'));
  206. $gmlType = 'LineString';
  207. }
  208. else if ('POINT' === $wktType) {
  209. $gmlCoordinatesFromWkt = $geomAsWkt;
  210. $gmlCoordinatesFromWkt = substr($gmlCoordinatesFromWkt, strlen('POINT('));
  211. $gmlCoordinatesFromWkt = substr($gmlCoordinatesFromWkt, 0, -1 * strlen(')'));
  212. $gmlCoordinatesFromWkt = str_replace(' ', ',', $gmlCoordinatesFromWkt);
  213. $gmlType = 'Point';
  214. }
  215. else {
  216. return null;
  217. }
  218. if($DBG){echo 'gmlCoordinatesFromWkt:';print_r($gmlCoordinatesFromWkt);echo "\n";}
  219. //$xmlWriter->startElement("gml:{$gmlType}");
  220. $xmlWriter->startElementNS('gml', $gmlType, 'http://www.opengis.net/gml');
  221. $xmlWriter->writeAttribute('srsName', "http://www.opengis.net/gml/srs/epsg.xml#4326");// TODO: EPSG
  222. if ('Point' === $gmlType) {
  223. $xmlWriter->startElement("gml:coordinates");
  224. //$coordinatesNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:gml', 'http://www.opengis.net/gml');
  225. //$coordinatesNode->setAttribute('decimal', '.');
  226. //$coordinatesNode->setAttribute('cs', ' ');
  227. //$coordinatesNode->setAttribute('ts', ',');
  228. $xmlWriter->text($gmlCoordinatesFromWkt);
  229. $xmlWriter->endElement();// gml:coordinates
  230. } else if ('LineString' === $gmlType) {
  231. $xmlWriter->startElement("gml:coordinates");
  232. $xmlWriter->writeAttribute('decimal', '.');
  233. $xmlWriter->writeAttribute('cs', ' ');
  234. $xmlWriter->writeAttribute('ts', ',');
  235. $xmlWriter->text($gmlCoordinatesFromWkt);
  236. $xmlWriter->endElement();// gml:coordinates
  237. } else {
  238. $xmlWriter->startElement('gml:outerBoundaryIs');
  239. $xmlWriter->startElement('gml:LinearRing');
  240. $xmlWriter->startElement('gml:coordinates');
  241. $xmlWriter->writeAttribute('decimal', '.');
  242. $xmlWriter->writeAttribute('cs', ' ');
  243. $xmlWriter->writeAttribute('ts', ',');
  244. $xmlWriter->text($gmlCoordinatesFromWkt);
  245. $xmlWriter->endElement();// gml:coordinates
  246. $xmlWriter->endElement();// gml:LinearRing
  247. $xmlWriter->endElement();// gml:outerBoundaryIs
  248. }
  249. $xmlWriter->endElement();// gml:{$gmlType}
  250. }
  251. }