Subversion Repositories eFlore/Projets.eflore-projets

Compare Revisions

Ignore whitespace Rev 726 → Rev 727

/trunk/services/modules/0.1/moissonnage/cartes/LegendeCartes.php
New file
0,0 → 1,64
<?php
 
class LegendeCartes {
const TYPE_MIME = 'application/json';
const ID_CLASSE = '10';
private $tableOntologies = '';
private $ontologies = array();
private $legende = array();
public function __construct() {
$this->tableOntologies = Config::get('bdd_table_ontologies');
}
public function obtenirLegende() {
$this->chargerOntologies();
$this->chargerLegende();
$resultat = new ResultatService();
$resultat->corps = $this->legende;
$resultat->mime = self::TYPE_MIME;
return $resultat;
}
private function chargerOntologies() {
$bdd = new Bdd();
$requete = "SELECT * FROM {$this->tableOntologies}";
$resultats = $bdd->recupererTous($requete);
if (!is_array($resultats) || count($resultats) <= 0) {
$message = "Les données d'ontologies n'ont pu être chargées pour la ressource demandée";
$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
throw new Exception($message, $code);
}
foreach ($resultats as $ontologie) {
$this->ontologies[$ontologie['id']] = $this->extraireComplementsOntologies($ontologie);
}
}
private function extraireComplementsOntologies($ontologie) {
if (strlen(trim($ontologie['complements'])) > 0) {
list($cle, $valeur) = explode('=', trim($ontologie['complements']));
$ontologie[trim($cle)] = trim($valeur);
}
return $ontologie;
}
private function chargerLegende() {
foreach ($this->ontologies as $ontologie) {
if ($ontologie['classe_id'] == self::ID_CLASSE && isset($ontologie['legende'])) {
$this->legende[] = array(
'code' => $ontologie['code'],
'couleur' => $ontologie['legende'],
'nom' => $ontologie['nom'],
'description' => $ontologie['description']
);
}
}
}
}
 
?>
/trunk/services/modules/0.1/moissonnage/cartes/DonneesFloradata.php
New file
0,0 → 1,52
<?php
 
final class DonneesFloradata extends SourceDonnees {
public function __construct($limitesCarte, $taxon, $source) {
parent::__construct($limitesCarte, $taxon, $source);
}
final public function recupererStations() {
$bdd = new Bdd();
$bdd->requeter("USE ".Config::get('bdd_nom_floradata'));
$condition = "longitude IS NULL OR latitude IS NULL OR longitude=0 OR latitude=0 ".
"OR longitude>180 OR latitude>90 OR mots_cles_texte LIKE '%sensible%'";
$requete =
"SELECT COUNT(id_observation) AS nb_observations, ".
"Floor(If({$condition},wgs84_latitude,latitude)*10)/10 AS lat, ".
"Floor(If({$condition},wgs84_longitude,longitude)*10)/10 AS lng ".
"FROM cel_obs LEFT JOIN cel_zones_geo cz ON ce_zone_geo=id_zone_geo ".
"WHERE transmission=1 AND ".$this->construireWhereTaxon()." AND ".
"(".
"(".
"longitude BETWEEN ".$this->limitesCarte['ouest']." AND ".$this->limitesCarte['est']." ".
"AND latitude BETWEEN ".$this->limitesCarte['sud']." AND ".$this->limitesCarte['nord'].
") OR (".
"({$condition}) AND ".
"wgs84_longitude BETWEEN ".$this->limitesCarte['ouest']." AND ".$this->limitesCarte['est']." ".
"AND wgs84_latitude BETWEEN ".$this->limitesCarte['sud']." AND ".$this->limitesCarte['nord'].
")".
") ".
"GROUP BY Floor(If({$condition},wgs84_latitude,latitude)*10)/10, Floor(If({$condition},wgs84_longitude,longitude)*10)/10 ".
"ORDER BY lat DESC, lng ASC";
return $bdd->recupererTous($requete);
}
final protected function construireWhereTaxon() {
$criteres = array();
$nomRang = $this->obtenirNomRang($this->taxon);
if ($nomRang == 'famille') {
$criteres[] = "famille=".$this->bdd->proteger($this->taxon['nom_sci']);
} else {
$criteres[] = "nt=".$this->taxon['num_taxonomique'];
$sousTaxons = $this->recupererSynonymesEtSousEspeces();
foreach ($sousTaxons as $sousTaxon) {
$criteres[] ="nt=".$sousTaxon['num_taxonomique'];
}
}
return "(".implode(' OR ',array_unique($criteres)).")";
}
}
 
?>
/trunk/services/modules/0.1/moissonnage/cartes/SourceDonnees.php
New file
0,0 → 1,49
<?php
 
abstract class SourceDonnees {
protected $limitesCarte = '';
protected $taxon = array();
protected $source = '';
public function __construct($limitesCarte, $taxon, $source) {
$this->limitesCarte = $limitesCarte;
foreach ($this->limitesCarte as $bord => $valeur) {
$this->limitesCarte[$bord] = str_replace(",", ".", round($valeur, 6));
}
$this->bdd = new Bdd();
$this->taxon = $taxon;
$this->source = $source;
}
abstract public function recupererStations();
abstract protected function construireWhereTaxon();
protected function obtenirNomRang() {
$nomsRangs = array('famille', 'genre', 'espece', 'sous_espece');
$rangs = explode(',', Config::get('rangs'));
for ($index = 0; $index < count($nomsRangs) && $rangs[$index] != $this->taxon['rang']; $index ++);
$position = $index == count($nomsRangs) ? count($nomsRangs)-1 : $index;
return $nomsRangs[$position];
}
protected function recupererSynonymesEtSousEspeces() {
$this->bdd->requeter("USE ".Config::get('bdd_nom'));
$requete =
"SELECT num_nom, nom_sci, num_taxonomique FROM bdtfx_v1_01 WHERE hierarchie LIKE '%-{$this->taxon['num_nom']}-%' ".
"OR num_taxonomique = {$this->taxon['num_taxonomique']}";
return $this->bdd->recupererTous($requete);
}
protected function recupererGenres() {
$this->bdd->requeter("USE ".Config::get('bdd_nom'));
$requete =
"SELECT num_nom, nom_sci, num_taxonomique FROM bdtfx_v1_01 WHERE rang=220 AND num_tax_sup={$this->taxon['num_nom']}";
return $this->bdd->recupererTous($requete);
}
}
 
?>
/trunk/services/modules/0.1/moissonnage/cartes/DonneesMoissonnage.php
New file
0,0 → 1,43
<?php
 
final class DonneesMoissonnage extends SourceDonnees {
public function __construct($limitesCarte, $taxon, $source) {
parent::__construct($limitesCarte, $taxon, $source);
}
final public function recupererStations() {
$bdd = new Bdd();
$bdd->requeter("USE ".Config::get('bdd_nom'));
$requete =
"SELECT Floor(lieu_station_latitude*10)/10 AS lat, Floor(lieu_station_longitude*10)/10 AS lng, ".
"COUNT(guid) AS nb_observations FROM {$this->source}_tapir WHERE ".$this->construireWhereTaxon()." ".
"AND lieu_station_longitude BETWEEN ".$this->limitesCarte['ouest']." AND ".$this->limitesCarte['est']." ".
"AND lieu_station_latitude BETWEEN ".$this->limitesCarte['sud']." AND ".$this->limitesCarte['nord']." ".
"GROUP BY Floor(lieu_station_latitude*10)/10, Floor(lieu_station_longitude*10)/10 ".
"ORDER BY lat DESC, lng ASC";
//echo $requete.'<br>';
return $bdd->recupererTous($requete);
}
final protected function construireWhereTaxon() {
$nomRang = $this->obtenirNomRang();
$criteres = array();
$criteres[] = "nom_scientifique_complet LIKE ".$this->bdd->proteger($this->taxon['nom_sci']."%");
if ($nomRang == 'espece') {
$sousTaxons = $this->recupererSynonymesEtSousEspeces();
foreach ($sousTaxons as $sousTaxon) {
$criteres[] = "nom_scientifique_complet LIKE ".$this->bdd->proteger($sousTaxon['nom_sci']."%");
}
} elseif ($nomRang == 'famille') {
$sousTaxons = $this->recupererGenres();
foreach ($sousTaxons as $sousTaxon) {
$criteres[] = "nom_scientifique_complet LIKE ".$this->bdd->proteger($sousTaxon['nom_sci']."%");
}
}
return "(".implode(' OR ',array_unique($criteres)).")";
}
}
 
?>
/trunk/services/modules/0.1/moissonnage/cartes/FormateurSVG.php
New file
0,0 → 1,303
<?php
 
class FormateurSVG {
private $documentXML;
private $coordonnees = array();
private $grille = null;
private $largeur = 0;
private $hauteur = 0;
private $typeMime = '';
private $format = 0;
private $sources = array();
private $image = null;
const ORIGINE = 20037508.342789244;
const MIME_MAP = 'text/html';
public function __construct($nomFichierSVG, $sources, $typeMime, $format) {
$this->chargerSVG($nomFichierSVG);
$this->chargerCoordonnees();
$this->construireParametresRetour($typeMime, $format);
$this->creerStyleSources();
$this->sources = $sources;
}
private function chargerSVG($nomFichierSVG) {
$this->documentXML = new DOMDocument("1.0", "UTF-8");
$this->documentXML->load($nomFichierSVG);
$this->supprimerNoeudsInutiles($this->documentXML->documentElement);
}
private function supprimerNoeudsInutiles(& $noeud) {
$index = 0;
while ($index < $noeud->childNodes->length) {
if (get_class($noeud->childNodes->item($index)) != 'DOMElement') {
$noeud->removeChild($noeud->childNodes->item($index));
} else {
$fils = $noeud->childNodes->item($index);
$this->supprimerNoeudsInutiles($fils);
$index ++;
}
}
}
private function chargerCoordonnees() {
$viewbox = $this->recupererNoeuds('qgisviewbox');
$this->coordonnees = array(
'xMin' => $viewbox->attributes->getNamedItem('xMin')->value,
'xMax' => $viewbox->attributes->getNamedItem('xMax')->value,
'yMin' => $viewbox->attributes->getNamedItem('yMin')->value,
'yMax' => $viewbox->attributes->getNamedItem('yMax')->value
);
}
private function recupererNoeuds($nomCouche) {
$contenuSVG = $this->documentXML->documentElement->childNodes;
$noeudCouche = null;
$index = 0;
while ($index < $contenuSVG->length && is_null($noeudCouche)) {
$id = $contenuSVG->item($index)->attributes->getNamedItem('id');
if ($id->value == $nomCouche) {
$noeudCouche = $contenuSVG->item($index);
}
$index ++;
}
$noeuds = null;
if (!is_null($noeudCouche)) {
$noeuds = $noeudCouche->firstChild;
}
return $noeuds;
}
private function construireParametresRetour($typeMime, $format) {
$viewBox = $this->documentXML->documentElement->attributes->getNamedItem('viewBox');
$limitesPixels = explode(' ',$viewBox->value);
$this->largeur = intval($limitesPixels[2]);
$this->hauteur = intval($limitesPixels[3]);
$this->typeMime = $typeMime;
$this->format = intval($format);
}
private function creerStyleSources() {
$couleurs = $this->recupererCouleursSources();
$reglesCss = array();
foreach ($couleurs as $codeSource => $codeCouleur) {
$reglesCss[] = ".{$codeSource} {\nfill:{$codeCouleur}\n}\n";
}
$texteCss = $this->documentXML->createCDATASection(implode(' ', $reglesCss));
$noeudStyle = new DomElement('style', '');
$this->documentXML->documentElement->appendChild($noeudStyle);
$noeudStyle->appendChild($texteCss);
}
private function recupererCouleursSources() {
$sourcesDonnees = Config::get('sourcesDonnees');
$codesSources = str_replace('floradata', 'cel', $sourcesDonnees).',tout';
$codes = explode(',', $codesSources);
for ($index = 0; $index < count($codes); $index ++) {
$codes[$index] = "'".$codes[$index]."'";
}
$codesSources = implode(',', $codes);
$bdd = new Bdd();
$requete = "SELECT code, SUBSTR(complements,9) AS couleur FROM ".Config::get('bdd_table_ontologies')." WHERE code IN ({$codesSources})";
$couleurs = $bdd->recupererTous($requete);
$listeCouleurs = array();
foreach ($couleurs as $couleur) {
$couleur['code'] = $couleur['code'] == 'cel' ? 'floradata' : $couleur['code'];
$listeCouleurs[$couleur['code']] = $couleur['couleur'];
}
return $listeCouleurs;
}
 
public function formaterCarte($taxon) {
$limitesCarte = $this->renvoyerLimitesCarte();
foreach ($this->sources as $source) {
$nomClasse = $source == 'floradata' ? 'DonneesFloradata' : 'DonneesMoissonnage';
$rechercheBdd = new $nomClasse($limitesCarte, $taxon, $source);
$stations = $rechercheBdd->recupererStations();
$this->ajouterStations($stations, $source);
}
$this->supprimerMaillesVides();
}
public function renvoyerLimitesCarte() {
$limites = array();
list($limites['ouest'], $limites['sud']) = $this->convertirMetresEnPixels(
$this->coordonnees['xMin'], $this->coordonnees['yMin']);
list($limites['est'], $limites['nord']) = $this->convertirMetresEnPixels(
$this->coordonnees['xMax'], $this->coordonnees['yMax']);
return $limites;
}
private function convertirMetresEnPixels($x, $y) {
$longitude = ($x / self::ORIGINE) * 180;
$latitude = ($y / self::ORIGINE) * 180;
$latitude = 180 / M_PI * (2 * atan(exp($latitude * M_PI / 180.0)) - M_PI / 2.0);
return array(round($longitude, 6), round($latitude, 6));
}
private function ajouterStations($stations, $source) {
$grille = $this->recupererNoeuds('grille')->childNodes;
$index = 0;
$maille = $grille->item($index);
foreach ($stations as $station) {
$idMaille = $maille->attributes->getNamedItem('id')->value;
$bbox = explode('_', substr($idMaille, 5));
$bbox[0] = floatval($bbox[0]);
$bbox[1] = floatval($bbox[1]);
while ($index < $grille->length && (
$bbox[1] > $station['lat'] || ($bbox[1] == $station['lat'] && $bbox[0] < $station['lng'])
)) {
$maille = $grille->item($index ++);
$idMaille = $maille->attributes->getNamedItem('id')->value;
$bbox = explode('_', substr($idMaille, 5));
$bbox[0] = floatval($bbox[0]);
$bbox[1] = floatval($bbox[1]);
}
if ($bbox[1] == $station['lat'] && $bbox[0] == $station['lng']) {
$this->genererTitreMaille($station['nb_observations'], $source, $maille);
$this->appliquerStyleMaille($source, $maille);
$maille = $grille->item($index ++);
}
if ($index == $grille->length) {
break;
}
}
}
private function supprimerMaillesVides() {
$grille = $this->recupererNoeuds('grille')->childNodes;
$index = 0;
while ($index < $grille->length) {
if (!$grille->item($index)->hasAttribute('title')) {
$grille->item($index)->parentNode->removeChild($grille->item($index));
} else {
$index ++;
}
}
}
private function appliquerStyleMaille($source, & $maille) {
$style = $maille->hasAttribute('class') ? 'tout' : $source;
$maille->setAttribute('class', $style);
}
private function genererTitreMaille($observations, $source, & $maille) {
$texte = '';
if ($maille->hasAttribute('title')) {
$texte = $maille->attributes->getNamedItem('title')->value."\n$source : $observations observations";
} else {
$texte = "$source : $observations observations";
}
$maille->setAttribute('title', $texte);
}
public function renvoyerCarte() {
$this->documentXML->documentElement->setAttribute("width", $this->format);
$this->documentXML->documentElement->setAttribute("height", $this->hauteur * $this->format / $this->largeur);
$retour = '';
if ($this->typeMime == self::MIME_MAP) {
$retour = $this->documentXML->saveHTML();
} else {
$retour = $this->convertirEnPng();
}
return $retour;
}
private function convertirEnPng() {
$this->image = imagecreatetruecolor($this->format, $this->hauteur * $this->format / $this->largeur);
imagefill($this->image, 0, 0, imagecolorallocate($this->image, 255, 255, 255));
$this->transformerLignesEnPng('departements');
$this->transformerPolygonesEnPng('grille');
// stocker le contenu encode de l'image generee dans une chaine de caracteres
ob_start();
imagepng($this->image);
$png = ob_get_contents();
ob_end_clean();
return $png;
}
private function transformerLignesEnPng($nomCouche) {
$facteur = floatval($this->format) / floatval($this->largeur);
$noeudCouche = $this->recupererNoeuds($nomCouche);
$couleurContour = $noeudCouche->attributes->getNamedItem('stroke')->value;
for ($index = 0; $index < $noeudCouche->childNodes->length; $index ++) {
$noeudLigne = $noeudCouche->childNodes->item($index);
for ($indexPath = 0; $indexPath < $noeudLigne->childNodes->length; $indexPath ++) {
$coordonneesSvg = $noeudLigne->childNodes->item($indexPath)->attributes->getNamedItem('points')->value;
preg_match_all('/\d+.\d/', $coordonneesSvg, $coordonnees);
$coordonnees = current($coordonnees);
foreach ($coordonnees as $indexCoord => $valeur) {
$coordonnees[$indexCoord] = intval(floatval($valeur) * $facteur);
}
if ($couleurContour != 'none') {
for ($i = 0; $i < count($coordonnees) - 2; $i += 2) {
imageline($this->image, $coordonnees[$i], $coordonnees[$i+1], $coordonnees[$i+2],
$coordonnees[$i+3], $this->allouerCouleur($couleurContour));
}
}
}
}
}
private function transformerPolygonesEnPng($nomCouche) {
$couleurs = $this->recupererCouleursSources();
$facteur = floatval($this->format) / floatval($this->largeur);
$noeudCouche = $this->recupererNoeuds($nomCouche);
$couleurRemplissage = $noeudCouche->attributes->getNamedItem('fill')->value;
$couleurContour = $noeudCouche->attributes->getNamedItem('stroke')->value;
for ($index = 0; $index < $noeudCouche->childNodes->length; $index ++) {
$noeudPolygone = $noeudCouche->childNodes->item($index);
$couleurPolygone = 'none';
if ($noeudPolygone->hasAttribute('class')) {
$couleurPolygone = $couleurs[$noeudPolygone->attributes->getNamedItem('class')->value];
}
for ($indexPath = 0; $indexPath < $noeudPolygone->childNodes->length; $indexPath ++) {
$coordonneesSvg = $noeudPolygone->childNodes->item($indexPath)->attributes->getNamedItem('points')->value;
preg_match_all('/\d+.\d/', $coordonneesSvg, $coordonnees);
$coordonnees = current($coordonnees);
foreach ($coordonnees as $indexCoord => $valeur) {
$coordonnees[$indexCoord] = intval(floatval($valeur) * $facteur);
}
if ($couleurRemplissage != 'none') {
imagefilledpolygon($this->image, $coordonnees, count($coordonnees) / 2, $this->allouerCouleur($couleurRemplissage));
}
if ($couleurContour != 'none') {
imagepolygon($this->image, $coordonnees, count($coordonnees) / 2, $this->allouerCouleur($couleurContour));
}
if ($couleurPolygone != 'none') {
$contourGrille = "rgba(255,255,255,".($this->format >= 300 ? 0.4 : 0).")";
imagefilledrectangle($this->image, $coordonnees[0], $coordonnees[1], $coordonnees[4], $coordonnees[5],
$this->allouerCouleur($couleurPolygone));
imagerectangle($this->image, $coordonnees[0], $coordonnees[1], $coordonnees[4], $coordonnees[5],
$this->allouerCouleur($contourGrille));
}
}
}
}
private function allouerCouleur($couleurTexte) {
preg_match_all('/\d+/', $couleurTexte, $valeurs);
$rouge = $valeurs[0][0];
$vert = $valeurs[0][1];
$bleu = $valeurs[0][2];
$alpha = 0;
if (count($valeurs[0]) > 3) {
$valeurAlpha = floatval($valeurs[0][3].".".$valeurs[0][4]);
$alpha = intval((1.0 - $valeurAlpha) * 127.0);
}
return imagecolorallocatealpha($this->image, $rouge, $vert, $bleu, $alpha);
}
}
 
?>