FortranGIS  Version2.5
readosm.F90
1 ! Copyright 2011 Davide Cesari <dcesari69 at gmail dot com>
2 !
3 ! This file is part of FortranGIS.
4 !
5 ! FortranGIS is free software: you can redistribute it and/or modify
6 ! it under the terms of the GNU Lesser General Public License as
7 ! published by the Free Software Foundation, either version 3 of the
8 ! License, or (at your option) any later version.
9 !
10 ! FortranGIS is distributed in the hope that it will be useful, but
11 ! WITHOUT ANY WARRANTY; without even the implied warranty of
12 ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 ! Lesser General Public License for more details.
14 !
15 ! You should have received a copy of the GNU Lesser General Public
16 ! License along with FortranGIS. If not, see
17 ! <http://www.gnu.org/licenses/>.
18 
44 MODULE readosm
45 use,INTRINSIC :: iso_c_binding
46 USE fortranc
47 IMPLICIT NONE
48 
49 
50 INTEGER,PARAMETER :: readosm_undefined = -1234567890
51 INTEGER,PARAMETER :: readosm_member_node = 7361
52 INTEGER,PARAMETER :: readosm_member_way = 6731
53 INTEGER,PARAMETER :: readosm_member_relation = 3671
54 INTEGER,PARAMETER :: readosm_ok = 0
55 INTEGER,PARAMETER :: readosm_invalid_suffix = -1
56 INTEGER,PARAMETER :: readosm_file_not_found = -2
57 INTEGER,PARAMETER :: readosm_null_handle = -3
58 INTEGER,PARAMETER :: readosm_invalid_handle = -4
59 INTEGER,PARAMETER :: readosm_insufficient_memory = -5
60 INTEGER,PARAMETER :: readosm_create_xml_parser_error = -6
61 INTEGER,PARAMETER :: readosm_read_error = -7
62 INTEGER,PARAMETER :: readosm_xml_error = -8
63 INTEGER,PARAMETER :: readosm_invalid_pbf_header = -9
64 INTEGER,PARAMETER :: readosm_unzip_error = -10
65 INTEGER,PARAMETER :: readosm_abort = -11
66 
69 TYPE,bind(c) :: readosm_tag
70  TYPE(c_ptr) :: key
71  TYPE(c_ptr) :: value
72 END TYPE readosm_tag
73 
76  CHARACTER(kind=c_char,len=1),ALLOCATABLE :: key(:)
77  CHARACTER(kind=c_char,len=1),ALLOCATABLE :: value(:)
78 END TYPE readosm_tag_f
79 
80 
90 TYPE,bind(c) :: readosm_node
91  INTEGER(kind=c_long_long) :: id
92  REAL(kind=c_double) :: latitude
93  REAL(kind=c_double) :: longitude
94  INTEGER(kind=c_int) :: version
95  INTEGER(kind=c_long_long) :: changeset
96  TYPE(c_ptr) :: user
97  INTEGER(kind=c_int) :: uid
98  TYPE(c_ptr) :: timestamp
99  INTEGER(kind=c_int) :: tag_count
100  TYPE(c_ptr) :: tags
101 END TYPE readosm_node
105  INTEGER(kind=c_long_long) :: id=0
106  REAL(kind=c_double) :: latitude
107  REAL(kind=c_double) :: longitude
108  INTEGER(kind=c_int) :: version
109  INTEGER(kind=c_long_long) :: changeset
110 ! TYPE(c_ptr) :: user !< name of the User defining this NODE
111  INTEGER(kind=c_int) :: uid
112 ! TYPE(c_ptr) :: timestamp !< when this NODE was defined
113  TYPE(readosm_tag_f),ALLOCATABLE :: tags(:)
114 END TYPE readosm_node_f
129 TYPE,bind(c) :: readosm_way
130  INTEGER(kind=c_long_long) :: id
131  INTEGER(kind=c_int) :: version;
132  INTEGER(kind=c_long_long) :: changeset
133  TYPE(c_ptr) :: user
134  INTEGER(kind=c_int) :: uid
135  TYPE(c_ptr) :: timestamp;
136  INTEGER(kind=c_int) :: node_ref_count
137  TYPE(c_ptr) :: node_refs
138  INTEGER(kind=c_int) :: tag_count
139  TYPE(c_ptr) :: tags
140 END TYPE readosm_way
144  INTEGER(kind=c_long_long) :: id=0
145  INTEGER(kind=c_int) :: version;
146  INTEGER(kind=c_long_long) :: changeset;
147 ! TYPE(c_ptr) :: user !< name of the User defining this WAY
148  INTEGER(kind=c_int) :: uid
149 ! TYPE(c_ptr) :: timestamp; !< when this WAY was defined
150  INTEGER(kind=c_long_long),ALLOCATABLE :: node_refs(:)
151  TYPE(readosm_tag_f),ALLOCATABLE :: tags(:)
152 END TYPE readosm_way_f
153 
161 TYPE,bind(c) :: readosm_member
162  INTEGER(kind=c_int) :: member_type
163  INTEGER(kind=c_long_long) :: id
164  TYPE(c_ptr) :: role
165 END TYPE readosm_member
166 
168 TYPE :: readosm_member_f
169  INTEGER(kind=c_int) :: member_type=readosm_undefined
170  INTEGER(kind=c_long_long) :: id
171  CHARACTER(kind=c_char,len=1),ALLOCATABLE :: role(:)
186 TYPE,bind(c) :: readosm_relation
187  INTEGER(kind=c_long_long) :: id
188  INTEGER(kind=c_int) :: version;
189  INTEGER(kind=c_long_long) :: changeset;
190  TYPE(c_ptr) :: user
191  INTEGER(kind=c_int) :: uid
192  TYPE(c_ptr) :: timestamp;
193  INTEGER(kind=c_int) :: member_count
194  TYPE(c_ptr) :: members
195  INTEGER(kind=c_int) :: tag_count;
196  TYPE(c_ptr) :: tags
201  INTEGER(kind=c_long_long) :: id
202  INTEGER(kind=c_int) :: version;
203  INTEGER(kind=c_long_long) :: changeset;
204 ! TYPE(c_ptr) :: user !< name of the User defining this RELATION
205  INTEGER(kind=c_int) :: uid
206 ! TYPE(c_ptr) :: timestamp; !< when this RELATION was defined
207  TYPE(readosm_member_f),ALLOCATABLE :: members(:)
208  TYPE(readosm_tag_f),ALLOCATABLE :: tags(:)
209 END TYPE readosm_relation_f
210 
211 ! define dynamically extensible arrays of the _f types, first part
212 #undef ARRAYOF_ORIGEQ
214 #undef ARRAYOF_ORIGTYPE
215 #undef ARRAYOF_TYPE
216 #define ARRAYOF_ORIGTYPE TYPE(readosm_node_f)
217 #define ARRAYOF_TYPE arrayof_readosm_node_f
218 #include "arrayof_pre.F90"
220 #undef ARRAYOF_ORIGTYPE
221 #undef ARRAYOF_TYPE
222 #define ARRAYOF_ORIGTYPE TYPE(readosm_way_f)
223 #define ARRAYOF_TYPE arrayof_readosm_way_f
224 #include "arrayof_pre.F90"
225 
226 #undef ARRAYOF_ORIGTYPE
227 #undef ARRAYOF_TYPE
228 #define ARRAYOF_ORIGTYPE TYPE(readosm_relation_f)
229 #define ARRAYOF_TYPE arrayof_readosm_relation_f
230 #include "arrayof_pre.F90"
231 
232 
238 TYPE readosm_full_f
239  TYPE(arrayof_readosm_node_f) :: nodes
240  TYPE(arrayof_readosm_way_f) :: ways
241  TYPE(arrayof_readosm_relation_f) :: relations
242 END TYPE readosm_full_f
243 
244 
250 INTERFACE
251  FUNCTION readosm_open(path, osm_handle) BIND(C,name='readosm_open')
252  import
253  CHARACTER(kind=c_char),INTENT(in) :: path(*)
254  TYPE(c_ptr),INTENT(out) :: osm_handle
255  INTEGER(kind=c_int) :: readosm_open
256  END FUNCTION readosm_open
257 END INTERFACE
258 
259 
265 INTERFACE
266  FUNCTION readosm_close(osm_handle) BIND(C,name='readosm_close')
267  import
268  TYPE(c_ptr),VALUE :: osm_handle
269  INTEGER(kind=c_int) :: readosm_close
270  END FUNCTION readosm_close
271 END INTERFACE
273 
278 INTERFACE readosm_parse
286  FUNCTION readosm_parse(osm_handle, user_data, node_fnct, way_fnct, &
287  relation_fnct) bind(c,name='readosm_parse')
288  import
289  TYPE(c_ptr),VALUE :: osm_handle
290  TYPE(c_ptr),VALUE :: user_data
291  TYPE(c_funptr),VALUE :: node_fnct
292  TYPE(c_funptr),VALUE :: way_fnct
293  TYPE(c_funptr),VALUE :: relation_fnct
294  INTEGER(kind=c_int) :: readosm_parse
295  END FUNCTION readosm_parse
296 
297  MODULE PROCEDURE readosm_parse_f
298 END INTERFACE readosm_parse
299 
300 
301 INTERFACE readosm_object_f
302  MODULE PROCEDURE readosm_object_f_node, readosm_object_f_way, &
303  readosm_object_f_relation
304 END INTERFACE readosm_object_f
305 
306 
307 INTERFACE readosm_parse
308 END INTERFACE readosm_parse
309 
310 PRIVATE readosm_object_f_node, readosm_object_f_way, &
311  readosm_object_f_relation
312 
313 CONTAINS
314 
322 FUNCTION readosm_parse_f(osm_handle, user_data, node_fnct, way_fnct, &
323  relation_fnct)
324 TYPE(c_ptr),VALUE :: osm_handle
325 TYPE(c_ptr),VALUE :: user_data
326 INTERFACE !< callback function intended to consume node objects (may be NULL if processing NODEs is not an interesting option)
327  FUNCTION node_fnct(user_data, node) BIND(C)
328  import
329  TYPE(c_ptr),VALUE :: user_data
330  TYPE(readosm_node) :: node
331  INTEGER(kind=c_int) :: node_fnct
332  END FUNCTION node_fnct
333 END INTERFACE
334 
336 INTERFACE
337  FUNCTION way_fnct(user_data, way) BIND(C)
338  import
339  TYPE(c_ptr),VALUE :: user_data
340  TYPE(readosm_way) :: way
341  INTEGER(kind=c_int) :: way_fnct
342  END FUNCTION way_fnct
343 END INTERFACE
344 
346 INTERFACE
347  FUNCTION relation_fnct(user_data, relation) BIND(C)
348  import
349  TYPE(c_ptr),VALUE :: user_data
350  TYPE(readosm_relation) :: relation
351  INTEGER(kind=c_int) :: relation_fnct
352  END FUNCTION relation_fnct
353 END INTERFACE
354 
355 OPTIONAL :: node_fnct
356 OPTIONAL :: way_fnct
357 OPTIONAL :: relation_fnct
358 INTEGER(kind=c_int) :: readosm_parse_f
359 
360 TYPE(c_funptr) :: nf, wf, rf
361 
362 IF (present(node_fnct)) THEN
363  nf = c_funloc(node_fnct)
364 ELSE
365  nf = c_null_funptr
366 ENDIF
367 IF (present(way_fnct)) THEN
368  wf = c_funloc(way_fnct)
369 ELSE
370  wf = c_null_funptr
371 ENDIF
372 IF (present(relation_fnct)) THEN
373  rf = c_funloc(relation_fnct)
374 ELSE
375  rf = c_null_funptr
376 ENDIF
377 
378 readosm_parse_f = readosm_parse(osm_handle, user_data, nf, wf, rf)
379 
380 END FUNCTION readosm_parse_f
381 
382 
383 ! private function for "fortranizing" tags array, it has been
384 ! temporarily converted to a subroutine because of (de)allocations
385 ! problems with gfortran 4.6.3
386 SUBROUTINE readosm_object_f_tags(tags, tag_count, f_type) ! RESULT(f_type)
387 TYPE(c_ptr) :: tags ! array of TAG objects (may be NULL)
388 INTEGER(kind=c_int) :: tag_count; ! number of associated TAGs (may be zero)
389 
390 TYPE(readosm_tag_f),INTENT(out),ALLOCATABLE :: f_type(:)
391 
392 TYPE(readosm_tag),POINTER :: tmptags(:)
393 INTEGER :: i
394 
395 IF (tag_count > 0 .AND. c_associated(tags)) THEN
396  CALL c_f_pointer(tags, tmptags, (/tag_count/))
397  ALLOCATE(f_type(tag_count))
398  DO i = 1, tag_count
399  f_type(i)%key = tmptags(i)%key
400  f_type(i)%value = tmptags(i)%value
401  ENDDO
402 ELSE
403  ALLOCATE(f_type(0))
404 ENDIF
405 
406 END SUBROUTINE readosm_object_f_tags
407 
408 
409 ! private function for "fortranizing" members array, it has been
410 ! temporarily converted to a subroutine because of (de)allocations
411 ! problems with gfortran 4.6.3
412 SUBROUTINE readosm_object_f_members(members, member_count, f_type) ! RESULT(f_type)
413 TYPE(c_ptr) :: members ! array of MEMBER objects (may be NULL)
414 INTEGER(kind=c_int) :: member_count; ! number of associated MEMBERs (may be zero)
415 
416 TYPE(readosm_member_f),INTENT(out),ALLOCATABLE :: f_type(:)
417 
418 TYPE(readosm_member),POINTER :: tmpmembers(:)
419 INTEGER :: i
420 
421 IF (member_count > 0 .AND. c_associated(members)) THEN
422  CALL c_f_pointer(members, tmpmembers, (/member_count/))
423  ALLOCATE(f_type(member_count))
424  DO i = 1, member_count
425  f_type(i)%member_type = tmpmembers(i)%member_type
426  f_type(i)%id = tmpmembers(i)%id
427  f_type(i)%role = tmpmembers(i)%role
428  ENDDO
429 ELSE
430  ALLOCATE(f_type(0))
431 ENDIF
432 
433 END SUBROUTINE readosm_object_f_members
434 
435 
436 FUNCTION readosm_object_f_node(c_type) RESULT(f_type)
437 TYPE(readosm_node),INTENT(in) :: c_type
438 
439 TYPE(readosm_node_f) :: f_type
440 
441 f_type%id = c_type%id
442 f_type%latitude = c_type%latitude
443 f_type%longitude = c_type%longitude
444 f_type%version = c_type%version
445 f_type%changeset = c_type%changeset
446 !f_type%user = c_type%user
447 f_type%uid = c_type%uid
448 !f_type%timestamp = c_type%timestamp
449 CALL readosm_object_f_tags(c_type%tags, c_type%tag_count, f_type%tags)
450 !f_type%tags = readosm_object_f_tags(c_type%tags, c_type%tag_count)
451 
452 END FUNCTION readosm_object_f_node
453 
454 
455 FUNCTION readosm_object_f_way(c_type) RESULT(f_type)
456 TYPE(readosm_way),INTENT(in) :: c_type
457 
458 TYPE(readosm_way_f) :: f_type
459 
460 INTEGER(kind=c_long_long),POINTER :: node_refs(:)
461 
462 f_type%id = c_type%id
463 f_type%version = c_type%version
464 f_type%changeset = c_type%changeset
465 !f_type%user = c_type%user
466 f_type%uid = c_type%uid
467 !f_type%timestamp = c_type%timestamp
468 IF (c_type%node_ref_count > 0 .AND. c_associated(c_type%node_refs)) THEN
469  CALL c_f_pointer(c_type%node_refs, node_refs, (/c_type%node_ref_count/))
470  f_type%node_refs = node_refs
471 ELSE
472  ALLOCATE(f_type%node_refs(0))
473 ENDIF
474 CALL readosm_object_f_tags(c_type%tags, c_type%tag_count, f_type%tags)
475 !f_type%tags = readosm_object_f_tags(c_type%tags, c_type%tag_count)
477 END FUNCTION readosm_object_f_way
478 
479 
480 FUNCTION readosm_object_f_relation(c_type) RESULT(f_type)
481 TYPE(readosm_relation),INTENT(in) :: c_type
482 
483 TYPE(readosm_relation_f) :: f_type
484 
485 f_type%id = c_type%id
486 f_type%version = c_type%version
487 f_type%changeset = c_type%changeset
488 !f_type%user = c_type%user
489 f_type%uid = c_type%uid
490 !f_type%timestamp = c_type%timestamp
491 CALL readosm_object_f_members(c_type%members, c_type%member_count, f_type%members)
492 CALL readosm_object_f_tags(c_type%tags, c_type%tag_count, f_type%tags)
493 !f_type%tags = readosm_object_f_tags(c_type%tags, c_type%tag_count)
494 
495 END FUNCTION readosm_object_f_relation
496 
497 
498 ! define dynamically extendible arrays of the _f types, second part
499 #undef ARRAYOF_ORIGEQ
500 
501 #undef ARRAYOF_ORIGTYPE
502 #undef ARRAYOF_TYPE
503 #define ARRAYOF_ORIGTYPE TYPE(readosm_node_f)
504 #define ARRAYOF_TYPE arrayof_readosm_node_f
505 #include "arrayof_post.F90"
506 
507 #undef ARRAYOF_ORIGTYPE
508 #undef ARRAYOF_TYPE
509 #define ARRAYOF_ORIGTYPE TYPE(readosm_way_f)
510 #define ARRAYOF_TYPE arrayof_readosm_way_f
511 #include "arrayof_post.F90"
512 
513 #undef ARRAYOF_ORIGTYPE
514 #undef ARRAYOF_TYPE
515 #define ARRAYOF_ORIGTYPE TYPE(readosm_relation_f)
516 #define ARRAYOF_TYPE arrayof_readosm_relation_f
517 #include "arrayof_post.F90"
518 
519 
529 FUNCTION readosm_parse_full_f(osm_handle, fulldata)
530 TYPE(c_ptr),VALUE :: osm_handle
531 TYPE(readosm_full_f),INTENT(inout),TARGET :: fulldata
532 INTEGER :: readosm_parse_full_f
533 
534 ! parse using the predefined callbacks
535 readosm_parse_full_f = readosm_parse(osm_handle, c_loc(fulldata), &
536  readosm_full_node, readosm_full_way, readosm_full_relation)
537 
538 CALL packarray(fulldata%nodes)
539 CALL packarray(fulldata%ways)
540 CALL packarray(fulldata%relations)
541 
542 END FUNCTION readosm_parse_full_f
543 
544 
548 FUNCTION readosm_full_node(user_data, node) BIND(C)
549 TYPE(c_ptr),VALUE :: user_data
550 TYPE(readosm_node) :: node
551 INTEGER(kind=c_int) :: readosm_full_node
552 
553 TYPE(readosm_full_f),POINTER :: fulldata
554 
555 ! cast user_data to the desired fortran object and insert the entity
556 ! in "Fortran-friendly" format
557 CALL c_f_pointer(user_data, fulldata)
558 CALL insert(fulldata%nodes, readosm_object_f(node))
559 ! set the return code to OK, otherwise parsing will stop
560 readosm_full_node = readosm_ok
561 
562 END FUNCTION readosm_full_node
563 
564 
568 FUNCTION readosm_full_way(user_data, way) BIND(C)
569 TYPE(c_ptr),VALUE :: user_data
570 TYPE(readosm_way) :: way
571 INTEGER(kind=c_int) :: readosm_full_way
572 
573 TYPE(readosm_full_f),POINTER :: fulldata
574 
575 ! cast user_data to the desired fortran object and insert the entity
576 ! in "Fortran-friendly" format
577 CALL c_f_pointer(user_data, fulldata)
578 CALL insert(fulldata%ways, readosm_object_f(way))
579 ! set the return code to OK, otherwise parsing will stop
580 readosm_full_way = readosm_ok
581 
582 END FUNCTION readosm_full_way
583 
584 
588 FUNCTION readosm_full_relation(user_data, relation) BIND(C)
589 TYPE(c_ptr),VALUE :: user_data
590 TYPE(readosm_relation) :: relation
591 INTEGER(kind=c_int) :: readosm_full_relation
592 
593 TYPE(readosm_full_f),POINTER :: fulldata
594 
595 ! cast user_data to the desired fortran object and insert the entity
596 ! in "Fortran-friendly" format
597 CALL c_f_pointer(user_data, fulldata)
598 CALL insert(fulldata%relations, readosm_object_f(relation))
599 ! set the return code to OK, otherwise parsing will stop
600 readosm_full_relation = readosm_ok
601 
602 END FUNCTION readosm_full_relation
603 
604 
605 END MODULE readosm
Open the .osm or .pbf file, preparing for future functions.
Definition: readosm.F90:486
Object describing a WAY structure.
Definition: readosm.F90:140
Derived type for performing a prepackaged full parsing of an osm file.
Definition: readosm.F90:473
Fortran 2003 interface to the readosm https://www.gaia-gis.it/fossil/readosm/index library...
Definition: readosm.F90:55
A more Fortran-friendly object describing a RELATION structure.
Definition: readosm.F90:211
Derived type defining a dynamically extensible array of TYPE(readosm_way_f) elements.
Definition: readosm.F90:330
Method for packing the array object reducing at a minimum the memory occupation, without destroying i...
Definition: readosm.F90:289
Derived type defining a dynamically extensible array of TYPE(readosm_node_f) elements.
Definition: readosm.F90:249
Object describing a TAG structure.
Definition: readosm.F90:80
A more Fortran-friendly object describing a TAG structure.
Definition: readosm.F90:86
Derived type defining a dynamically extensible array of TYPE(readosm_relation_f) elements.
Definition: readosm.F90:411
Utility module for supporting Fortran 2003 C language interface module.
Definition: fortranc.F90:100
Parse the corresponding file calling the selected callbacks for every entity encountered.
Definition: readosm.F90:513
A more Fortran-friendly object describing a NODE structure.
Definition: readosm.F90:115
A more Fortran-friendly object describing a RELATION-MEMEBER structure.
Definition: readosm.F90:179
Method for inserting elements of the array at a desired position.
Definition: readosm.F90:257
Object describing a RELATION-MEMBER structure.
Definition: readosm.F90:172
A more Fortran-friendly object describing a WAY structure.
Definition: readosm.F90:154
Close the .osm or .pbf file and release any allocated resource.
Definition: readosm.F90:501
Object describing a RELATION structure.
Definition: readosm.F90:197
Object describing a NODE structure.
Definition: readosm.F90:101