User:Mga geo/osmapi.pl

From OpenStreetMap Wiki
Jump to: navigation, search
#!/usr/bin/perl
#
# osmapi.pl
# auteur: Marc GAUTHIER
#
#
use strict;
use warnings;
use Carp;
use Data::Dumper;
use Utils;
  select (STDERR);$|=1;
  select (STDOUT);$|=1;
  our $self->{DEBUG} = 0;
  our $CommunesDir = '../35/communes/';
  if ( ! -d $CommunesDir ) {
    mkdir $CommunesDir;
  }
  my ( $sp );
  $sp = 'xapi';
  $sp = 'osm2kml';
  warn "$0 sp:$sp";
  my $sub = UNIVERSAL::can('main',"$sp");
  if ( defined $sub ) {
    &$sub(@ARGV);
  } else {
    warn "main sp:$sp inconnu";
  }

  exit;
# conversion de fichiers osm en fichier kml
# lit un fichier csv contenant les id des relations à prendre en compte
# le fichier correspondant à chaque id est lu
# pour chaque chemin/way, le segment est calculé
# ce segment est simplifié (diminution du nombre de points)
# le kml est généré
#
# 
sub osm2kml {
  my ( $oa, $id, $tag, %id,$nb_id, $i_id, $f_csv, $f_osm );
  csv_hash("../35/communes.csv","id",\%id);
  $nb_id = scalar(keys %id);
  warn "osm2kml() nb_id:$nb_id";
  $i_id = 0;
  for $id ( keys %id ) {
    $oa = new OsmApi;
    $i_id++;
    if ( $id{$id}->{'ref:INSEE'} ne '35288' ) {
#      next;
    }
    warn "osm2kml() id:$id $i_id/$nb_id ref:INSEE:".$id{$id}->{'ref:INSEE'}." ".$id{$id}->{name};
    if ( $id{$id}->{'ref:INSEE'} !~ /^\d{5}$/ ) {
      confess;
    }
    $f_osm = "../35/communes/${id}.osm";
    $oa->{osm} = '';
    if ( ! -f $f_osm ) {
      $oa->getRelation($id);
      $oa->ecritOSM($f_osm);
    }
    if ( -f $f_osm ) {
      $oa->litOSM($f_osm);
      $oa->analyseOSM();
    }
    $oa->ajouteLigneWay();
    $oa->osm2commune($CommunesDir.$id{$id}->{'ref:INSEE'}.".kml");
#    $oa->clean();
#    warn "osm2kml() nb_relations:".scalar(keys%{$oa->{relation}} );
    
    if ( $i_id > 1000 ) {
      last;
    }
  }
  return;
  $oa->ajouteLigneWay();
#	$oa->{DEBUG} = 10;
  $oa->osm2commune("../35/communes.kml");
}
# extraction avec xapi sur une zone
sub xapi {
  my ( $oa, $id, $tag, %id,$nb_id, $i_id, $f_csv, $f_osm );
  $oa = new OsmApi;
  $oa->setBbox('-2.26,47.55,-1.02,48.75');
#  $oa->setBbox('-1.7155,48.0256,-1.4645,48.2102');
  $tag = 'relation';
  $tag = 'node';
  $oa->getXapi($tag);
  $oa->ecritOSM("../35/bbbox_${tag}.osm");
  return;
}
# http://www.openstreetmap.org/browse/relation/973226
sub grab {
  my ( $oa, $id, $tag, %id,$nb_id, $i_id, $f_csv, $f_osm );
  $oa = new OsmApi;
#  $oa->setBbox('-2.26,47.55,-1.02,48.75');
#  $oa->setBbox('-1.7155,48.0256,-1.4645,48.2102');
# liste des communes à partir de leur limites administratives
  $oa->litOSM("../35/35_rel.osm");
  $oa->analyseOSM();
  $oa->{DEBUG} = 0;
  my $csv = $oa->extraitCommunes();
  putLignes("../35/communes.csv",$csv);
  return;
# extraction avec xapi sur une zone
  $tag = 'relation';
  $tag = 'node';
  $oa->getXapi($tag);
  $oa->ecritOSM("../35/bbbox_${tag}.osm");
  return;
# production du fichier kml pour une commune
  $id = '78150'; # Cesson
  $oa->litOSM("../35/${id}.osm");
  $oa->analyseOSM();
#  warn Dumper \$oa->{'way'};
#  $oa->{DEBUG} = 1;
  $oa->osm2commune("../35/${id}.kml");

  return;
  $oa->litOSM("../35/${id}.osm");
  $id = '973226'; # Antrain
  $oa->getRelation($id);
  $oa->ecritOSM("../35/${id}.osm");
  return;
}
#
# la partie requete http pour obtenir les informations
#
package OsmApi;
use strict;
use Carp;
use Data::Dumper;
use MIME::Base64;
use HTTP::Request::Common;
use LWP::UserAgent;
use URI;
use Encode;
use HTML::Entities;
use Poly;
sub new {
  my( $class, %attr ) = @_;
  my $self =  {
    DEBUG => 0,
  };
  bless($self, $class);
  $self->{ua} =  new LWP::UserAgent(agent => 'mgaClientV6', timeout => 120);
  if( defined $attr{username} and defined $attr{password} ) {
#    my $encoded = MIME::Base64::encode_base64("$attr{username}:$attr{password}","");
#    $self->{ua}->default_header( "Authorization", "Basic $encoded" );
    $self->{ua}->credentials('www.openstreetmap.org:80','Web Password',$attr{username},$attr{password});
  }
# filtrage par boite ?
  if( defined $attr{'bbox'} ) {
    $self->setBbox($attr{'bbox'});
  }
  if ( defined $ENV{HTTP_PROXY} ) {
    $self->{ua}->proxy(['http'], $ENV{HTTP_PROXY});
  }
  $self->{osm} = <<'EOF';
<?xml version='1.0' encoding="UTF-8"?>
<osm version="0.6" generator="perl OsmApi">
EOF
  return $self;
}
sub clean {
  $self->{osm} = '';
  $self->{kml} = '';
  $self->{'content'} = '';
  undef $self->{ways};
  undef $self->{way};
  undef $self->{nodes};
  undef $self->{node};
  for my $id ( keys %{$self->{relation}} ) {
    delete$self->{relation}{$id};
  }  
  warn "clean() nb_relations:".scalar(keys%{$self->{relation}} );
}
#
# mise en place de la boite englobante
sub setBbox {
  my $self = shift;
  my $bbox = shift;
  my ($minlon, $minlat, $maxlon, $maxlat) = split(",", $bbox);
  if ( not defined($maxlon) ) {
    confess "setBbox($bbox) mauvais format";
  }
  if ( $maxlon < $minlon ) {
    confess "setBbox($bbox)  $maxlon < $minlon";
  }
  if ( $maxlat < $minlat ) {
    confess "setBbox($bbox)  ($maxlat < $minlat";
  }
  $self->{'bbox'} = $bbox;
  ($self->{minlat}, $self->{minlon}, $self->{maxlat}, $self->{maxlon} ) =  ($minlat, $minlon, $maxlat, $maxlon);
}
#
# mise en place de la boite englobante
sub LatLoninBbox {
  my ($self, $lat, $lon) = @_;
  if ( not defined  $self->{maxlon} ) {
    return 1;
  }
  return 0 if (($lat < $self->{minlat}) || ($lat > $self->{maxlat}));
  return 0 if (($lon < $self->{minlon}) || ($lon > $self->{maxlon}));
  return 1
}
#
# écrit le fichier osm
sub ecritOSM {
  my $self = shift;
  my $f_osm = shift;
# ajout des tags xml et osm si besoin
  if ( $self->{osm} !~ m{^<\?xml} ) {
    $self->{osm} = <<'EOF' . $self->{osm};
<?xml version='1.0' encoding="UTF-8"?>
<osm version="0.6" generator="perl OsmApi">
EOF
  }
  if ( $self->{osm} !~ m{</osm>} ) {
      $self->{osm} .= <<'EOF';
</osm>
EOF
  }
#  open(OSM, ">:encoding(UTF-8)", $f_osm) or confess "ecritOSM() open(OSM, >:encoding(UTF-8), $f_osm) erreur:$!";
  open(OSM, ">", $f_osm) or confess "ecritOSM() open(OSM, $f_osm) erreur:$!";
  print OSM $self->{osm};
  close(OSM);
  warn "ecritOSM() $f_osm"; 
  $self->{osm} = '';
}
# lit le fichier osm
sub litOSM {
  my $self = shift;
  my $f_osm = shift;
  warn "litOSM($f_osm)";
  open(OSM, $f_osm) or confess "litOSM() open(OSM, $f_osm) erreur:$!";
  $self->{osm} = join('',<OSM>);
  $self->{'content'} = $self->{'osm'};
  close(OSM);
}
#
# un get en http
# met à jour  $self->{content}
sub get {
  my $self = shift;
  my $url = shift;
  warn "get($url)";
  my $req = new HTTP::Request 'GET' => $url;
  my $res = $self->{ua}->request($req);
  $self->{content} = '';
  if ($res->is_success) {
    $self->{content} = $res->content;
  } else {
    warn "get($url) Error: " . $res->status_line;
  }
  $self->{content} =~ s{.*generator="OpenStreetMap server">.}{}s;
  $self->{content} =~ s{</osm>.*}{}s;
  $self->{osm} .=  $self->{content};
#  confess $self->{content};
}
#
# extraction des communes:
# relations avec admin_level=8
sub extraitCommunes {
  my $self = shift;
  my $relation = $self->{relation};
  my $csv = '';
  $csv .= sprintf("%s;%s;%s\n","id","name","ref:INSEE");
  for my $relation_id ( keys %{$self->{relation}} ) {
# type=boundary,
    if ( not defined $self->{relation}->{$relation_id}{tag}{'admin_level'} ) {
      next;
    }
    if ( $self->{relation}->{$relation_id}{tag}{'admin_level'} != 8 ) {
      next;
    }
    if ( not defined  $self->{relation}->{$relation_id}{tag}{'ref:INSEE'} ) {
      warn "relation_id:$relation_id manque ref:INSEE";
      next;
    }
    if (  $self->{relation}->{$relation_id}{tag}{'ref:INSEE'} !~ m{^35} ) {
      next;
    }
    $csv .= sprintf("%s;%s;%s\n",$relation_id,$self->{relation}->{$relation_id}{tag}{'name'},$self->{relation}->{$relation_id}{tag}{'ref:INSEE'});
    warn"extraitCommunes() relation_id:$relation_id name:". $self->{relation}->{$relation_id}{tag}{'name'}
      . " ref:INSEE:". $self->{relation}->{$relation_id}{tag}{'ref:INSEE'} if $self->{'DEBUG'};
  }
  return $csv;
}
# http://wiki.openstreetmap.org/wiki/API_v0.6
#
# recuperation des communes:
# relations avec admin_level=8
sub getXapi {
  my $self = shift;
  my $tag = shift;
# on augmente le time-out à 4 minutes
  $self->{ua}->timeout(240);
  if ( $tag eq 'relation' ) {
    $self->get("http://xapi.openstreetmap.org/api/0.6/relation[admin_level=8][bbox=$self->{bbox}]");
  }
  if ( $tag eq 'node' ) {
    $self->get("http://xapi.openstreetmap.org/api/0.6/node[place=town|city|village|hamlet][bbox=$self->{bbox}]");
  }
}
# http://wiki.openstreetmap.org/wiki/API_v0.6
#
# récuperation d'une relation
sub getRelation {
  my $self = shift;
  my $id = shift;
  my $element = 'relation';
  @{$self->{ways}} = ();
  $self->get("http://www.openstreetmap.org/api/0.6/$element/$id/full");
  $self->analyseOSM();
  my $nb_ways = scalar( @{$self->{ways}}) ;
  warn "getRelation() nb_ways: $nb_ways";
  return;
#  warn Dumper $self->{relation};
# parcours des membres (way) à la recherche des noeuds
#
  @{$self->{nodes}} = ();
  for my $way_id ( @{$self->{ways}} ) {
    $self->get("http://www.openstreetmap.org/api/0.6/way/$way_id");
    $self->analyseOSM();
  }
  my $nb_nodes = scalar( @{$self->{nodes}}) ;
  warn "getRelation() nb_nodes: $nb_nodes";
#  return;
# un noeud peut appartenir à deux ways
  my $i_nodes = 0;
  for my $node ( @{$self->{nodes}} ) {
    $i_nodes++;
    warn "getRelation() $i_nodes/$nb_nodes";
    $self->get("http://www.openstreetmap.org/api/0.6/node/$node");
#    return;
  }
}
#
# analyse d'une réponse OSM au format xml
# les différentes informations sont remontées dans des hashes: relation, way, node
# l'id sert d'index
sub analyseOSM {
  my $self = shift;
  warn "analyseOSM() debut nb_relations:".scalar(keys %{$self->{relation}});
  my ( %element, $element, $id, @attr, $attr, $tags, $line, $regexp );
  $regexp = 'node|way|relation';
  if ( @_ ) {
    $regexp = 'relation';
    $regexp = shift;
  }
  $element = '';
  for $line ( split("\n",$self->{content}) ) {
# un nouvel objet
    if ( $line =~ m{^\s*<($regexp).*\sid=["']([^"']+)["']} ) {
      $element = $1;
      $id = $2;
      $element{$element}++;
      warn "analyseOSM() object:$element id:$id" if $self->{DEBUG};
# on l'a déjà eu! on recommence
      if ( defined $self->{$element}->{$id} ) {
        delete $self->{$element}->{$id};
      }
      $attr = {};
      $tags = {};
# les attributs
      @attr = $line =~ m{(\w+)=['"](.*?)['"]}g;
      while ( @attr ) {
        my $key = shift @attr;
        my $value = shift @attr;
        $self->{$element}->{$id}->{$key} = $value;
      }
# la mémorisation de la lonlat pour les nodes
      if ( $element eq 'node' ) {
        if ( $self->LatLoninBbox($self->{$element}->{$id}->{lat},$self->{$element}->{$id}->{lon}) ) {
          $self->{$element}->{$id}->{lonlat} = $self->{$element}->{$id}->{lon} . ',' . $self->{$element}->{$id}->{lat};
        } else {
          delete $self->{$element}->{$id};
          warn "analyseOSM() hors zone:$element $id ";
        }
      }
      next;
    }
# la fin d'un object
    if ( $element ne '' && ( $line =~ m{^\s*</(node|way|relation)} or $line =~ m{^\s*<(node|way|relation).*/>} ) ) {
      $element = '';
      next;
    }
# node ref
    if ( $element eq 'way' && $line =~ /^\s*<nd.*\sref=["']([^"']+)["']/  ) {
      push @{$self->{nodes}}, $1;
      push @{$self->{$element}->{$id}->{ref}}, $1;
      next;
    }

# les membres des relations
    if ( $element eq 'relation' && $line =~ /^\s*<member/  ) {
# les attributs
      @attr = $line =~ m{(\w+)=['"](.*?)['"]}g;
      $attr = {};
      while ( @attr ) {
        my $key = shift @attr;
        my $value = shift @attr;
        $attr->{$key} = $value;
      }
# on mémorise les ways pour recherche ultérieure
      if ( defined $attr->{'type'} && $attr->{'type'} eq 'way' ) {
        push @{$self->{ways}}, $attr->{'ref'};
      }
#      push @{$self->{$element}->{$id}->{ref}}, $attr;
      warn "analyseOSM() $element:$id $line ref:".$attr->{'ref'} if $self->{'DEBUG'};
      push @{$self->{$element}->{$id}->{ref}}, $attr->{'ref'};
      next;
    }
# les tags des relations
#    <tag k='admin_level' v='8'/>
    if ( $element eq 'relation' &&  $line =~ /^\s*<tag k=["']([^']+)["'] v=["']([^']+)["']/) {
      warn "analyseOSM() $element:$id tag $1=>$2" if ( $self->{'DEBUG'} );
      $tags->{$1} = $2;
      $self->{$element}->{$id}->{tag}->{$1} = $2;
      next;
    }
  }
  warn "analyseOSM() fin nb_relations:".scalar(keys %{$self->{relation}})." nb_nodes:".$element{'node'};
}
sub osm2commune {
  my $self = shift;
  my $f_kml = shift;
  warn "osm2commune() nb_relations:".scalar(keys%{$self->{relation}} );
  $self->kml_debut();
  for my $relation_id ( keys %{$self->{relation}} ) {
    $self->kml_commune($relation_id);
  }
  $self->kml_fin($f_kml);
}
# ---------------------------------------------------------------------------------------------
#
# l'entête du fichier kml
sub kml_debut {
  my $self = shift;
  $self->{kml} = <<'EOF';
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.2">
<Document>
  <name>OSM admin-level=8</name>
  <author>
    <name>Marc Gauthier</name>
  </author>
  <Style id="orange">
    <LineStyle>
     <color>ff00aaff</color>
      <width>2</width>
    </LineStyle>
    <PolyStyle>
      <color>660020e0</color>
    </PolyStyle>
  </Style>
<Folder>
<name>Contours</name>
<open>0</open>
EOF
}
#
# la fin du fichier kml
sub kml_fin {
  my $self = shift;
  my $f_kml = shift;
  $self->{kml} .= <<'EOF';
</Folder>
</Document>
</kml>
EOF
#  open(KML,">:encoding(UTF-8)", "$f_kml") or die "open(KML,>$f_kml) erreur:$!";
  open(KML,">", "$f_kml") or die "open(KML,>$f_kml) erreur:$!";
  print KML $self->{kml};
  close(KML);
  warn "kml_fin() f_kml: $f_kml";
}
#
# le kml pour une commune
# le contour de la commune est constitué de plusieurs lignes
# deux méthodes, on les met dans une MultiGeometry
# - LineString
# - Polygon
# Cas difficile: les role="exclave"
# plusieurs polygones
# 909651;Tresbœuf;35343 une enclave
# 905534;Saint-Malo;35288 les îles
# 145072;Saint-Briac-sur-Mer;35256
# 108303;Cancale;35049
# Iffendic: - 2 trous au sud de Boisgervilly, à l'ouest d'Iffendic
# http://wiki.openstreetmap.org/wiki/Relation:boundary
# http://code.google.com/p/pyosm/source/browse/tools/osm2mp-preprocess.py?spec=svnf33b378075455c4963d1d712dd5fd0528b6cec3d&r=f33b378075455c4963d1d712dd5fd0528b6cec3d
# http://wiki.openstreetmap.org/wiki/Key:place
# http://wiki.openstreetmap.org/wiki/FR:Key:place
sub kml_commune {
  my $self = shift;
  my $relation_id = shift;
  if ( not defined  $self->{relation}->{$relation_id}{tag}{'name'} ) {
    confess Dumper  $self->{relation}->{$relation_id};
  }
  if ( $self->{relation}->{$relation_id}{tag}{'admin_level'} ne 8 ) {
    return;
  }
  warn "kml_commune() $relation_id:".$self->{relation}->{$relation_id}{tag}{'name'};
  my ( $kml_multi, $kml_line );
  $self->{kml} .= <<EOF;
<Placemark>
<desc>$self->{relation}->{$relation_id}{tag}{'name'}</desc>
<name>$self->{relation}->{$relation_id}{tag}{'ref:INSEE'}</name>
<styleUrl>#orange</styleUrl>
EOF
  $kml_multi = <<EOF;
<MultiGeometry>
EOF
  my ( %segment, @segment, $deb, $fin, %coord, $coord, $way_id, @ajout );
  warn "kml_commune() relation_id:$relation_id nb_ref:".scalar(@{$self->{relation}->{$relation_id}{'ref'}}) if $self->{DEBUG};
  for $way_id (  @{$self->{relation}->{$relation_id}{'ref'}} ) {
    warn "kml_commune() relation_id:$relation_id way_id:$way_id" if $self->{DEBUG};
    if ( not defined $self->{way}->{$way_id} ) {
      warn "kml_commune() relation_id:$relation_id way_id:$way_id absent" if $self->{DEBUG};
#      confess Dumper $self->{way};
      next;
    }
    if ( not defined $self->{way}->{$way_id}{'coord'} ) {
      next;
    }
    warn "kml_commune() relation_id:$relation_id way_id:$way_id nb_nodes:".scalar(@{$self->{way}->{$way_id}{'coord'}})  if $self->{DEBUG};
    $kml_multi .= <<EOF;
<LineString><coordinates>
EOF
    $kml_multi .= join("\n",@{$self->{way}->{$way_id}{'coord'}});
    $kml_multi .= <<EOF;
</coordinates></LineString>
EOF
    $deb = $self->{way}->{$way_id}{'coord'}[0];
    $fin = $self->{way}->{$way_id}{'coord'}[-1];
    warn "kml_commune() relation_id:$relation_id way_id:$way_id deb:$deb fin:$fin nb_coord:".scalar(@{$self->{way}->{$way_id}{'coord'}}) if $self->{DEBUG};
    $coord{$way_id}{'deb'} = $deb;
    $coord{$way_id}{'fin'} = $fin;
  }
  $kml_multi .= <<EOF;
</MultiGeometry>
</Placemark>
EOF
# assemblage des lignes en polygone
# on commence avec la première ligne récupérée, !!! hors exclave !!!
# on peut avoir plusieurs polygones!!! les exclaves
# @lignes contient les way_id des différentes lignes
# @segment contient le polygone en cours de construction
#  $self->{DEBUG} = 1;
  my ( @lignes );
  @segment = ( 0,0 );
  my @polygone = ();
#	warn Dumper \%coord if $self->{DEBUG};
  warn "kml_commune() relation_id:$relation_id nb_lignes:",scalar(@lignes) if $self->{DEBUG};
  my $i_polygone = -1;
  for ( my $i=0; $i <1000;$i++ ) {
#	  warn Dumper \@segment;
    warn "kml_commune() relation_id:$relation_id i:$i polygone de nb_segment:".scalar(@segment) if $self->{DEBUG};
      $i_polygone++;
      $polygone[$i_polygone] = [@segment];
    @lignes = keys %coord;
    if ( @lignes ) {
      $way_id = shift @lignes;
        delete $coord{$way_id};
      @segment = @{$self->{way}->{$way_id}{'coord'}};
      } else {
      warn "kml_commune() relation_id:$relation_id i:$i plus de lignes" if $self->{DEBUG};
        last;
      }
# ajout de lignes tant que c'est possible
# il faut rechercher la way_id qui commence ou fini avec ces coordonnées
    for ( my $j=0; $j < 1000; $j++) {
      if ( $segment[0] eq $segment[-1] ) {
        last;
    }
    $fin = $segment[-1];
      warn "kml_commune() relation_id:$relation_id i:$i nb_segments:".scalar(@segment)." reste nb_lignes:".scalar(@lignes) if $self->{DEBUG};
    @ajout = ();
    for $way_id ( keys %coord ) {
# le segment est dans le bon ordre
      if ( $coord{$way_id}{'deb'} eq $fin ) {
        warn "kml_commune() relation_id:$relation_id i:$i  fin:$fin ajout bon ordre de way_id:$way_id" if $self->{DEBUG};
        delete $coord{$way_id};;
        @ajout = @{$self->{way}->{$way_id}{'coord'}};
        last;
      }
# le segment est dans le mauvais ordre
      if ( $coord{$way_id}{'fin'} eq $fin ) {
        warn "kml_commune() relation_id:$relation_id i:$i fin:$fin ajout ordre inverse way_id:$way_id" if $self->{DEBUG};
        delete $coord{$way_id};;
        @ajout = reverse(@{$self->{way}->{$way_id}{'coord'}});
        last;
      }
    }
    if ( @ajout ) {
      if ( $ajout[0] ne $segment[-1] ) {
        warn "kml_commune() relation_id:$relation_id i:$i BUG";
        confess Dumper \@ajout;
      }
      shift @ajout;
      warn "kml_commune() relation_id:$relation_id i:$i ajout nb_segments:",scalar(@ajout) if $self->{DEBUG};
      push @segment, @ajout;
    } else {
      last;
    }
  }
  }
  shift @polygone;
#  confess Dumper \@polygone;
  $self->{kml} .= <<EOF;
<MultiGeometry>
EOF
  warn "kml_commune() nb_polygone:",scalar(@polygone) if $self->{DEBUG};
  for my $segment ( @polygone ) {
    @segment = @{$segment};
# début égal à la fin ?
    $coord = join("\n",@segment);
    $kml_line = <<EOF;
<LineString>
<coordinates>
$coord
</coordinates>
</LineString>
EOF
    $kml_line = <<EOF;
<Polygon>
<outerBoundaryIs>
<LinearRing>
<coordinates>
$coord
</coordinates>
</LinearRing>
</outerBoundaryIs>
</Polygon>
EOF
#  confess Dumper \@segment;
    $self->{kml} .= $kml_line;
  }
  $self->{kml} .= <<EOF;
</MultiGeometry>
</Placemark>
EOF
  $self->{nb_placemark}++;
}
#
# transformation des noeuds d'une way en une ligne
sub ajouteLigneWay {
  my $self = shift;
  warn "ajouteLigneWay debut nb_ways:".scalar(keys %{$self->{way}});
  my ( $way_id, $node_id );
  for $way_id ( keys %{$self->{way}} ) {
    warn "ajouteLigneWay way_id:$way_id" if $self->{DEBUG};
    @{$self->{way}->{$way_id}{'coord'}} = ();
    for $node_id (  @{$self->{way}->{$way_id}->{ref}} ) {
      if ( not defined $self->{node}->{$node_id} ) {
        warn "ajouteLigneWay way_id:$way_id node_id:$node_id absent" if $self->{DEBUG};
        next;
      }
      push @{$self->{way}->{$way_id}{'coord'}},$self->{node}->{$node_id}->{lonlat};
    }
    $self->Douglas_Peucker($way_id);
  }
}
#
# diminution du nombre de points
sub Douglas_Peucker {
  my $self = shift;
  my $way_id = shift;
  my ( @Ipoints, @Opoints, $lon, $lat, $coord, @reste);
  @Ipoints = ();
  for $coord ( @{$self->{way}{$way_id}->{coord}} ) {
    ($lon, $lat, @reste) = split ',', $coord;
    push( @Ipoints, [$lat,$lon] ) ;
  }
  @Opoints = Poly::Douglas_Peucker( \@Ipoints, 100 ) ;
#    warn "Douglas_Peucker() ".scalar(@Ipoints)."=>".scalar(@Opoints);
  @{$self->{way}{$way_id}->{coord}} = ();
  for $coord ( @Opoints ) {
#			confess Dumper \$coord;
    push @{$self->{way}{$way_id}->{coord}},$coord->[1].",".$coord->[0];
  }
}