New file |
0,0 → 1,321 |
<?php |
|
/** |
* Classe qui genere la carte SVG pour les parametres de la requete qui a ete utilisee pour appeler |
* le web service |
* |
* @package framework-0.4 |
* @author Alexandre GALIBERT <alexandre.galibert@tela-botanica.org> |
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt> |
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt> |
* @version $Id$ |
* @copyright 2013 Tela Botanica (accueil@tela-botanica.org) |
* |
*/ |
|
|
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); |
} |
|
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(); |
$sourceDonnees = new SourceDonnees($limitesCarte, $taxon); |
// modification temporaire pour lors de la selection d'un rang au dessus de famille on ne prenne que floradata |
// (probleme de performance, qui sera réglé en reremplissant la table de moissonnage) |
if($taxon['rang'] >= 180) { |
foreach ($this->sources as $source) { |
$nomMethode = "recupererStations".($source == 'floradata' ? 'Floradata' : 'Moissonnage'); |
$stations = $sourceDonnees->$nomMethode($source); |
$this->ajouterStations($stations, $source); |
} |
} else { |
$stations = $sourceDonnees->recupererStationsFloradata($source); |
$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) { |
if (!isset($station['lat']) || !isset($station['lng']) || !isset($station['commune'])) { |
continue; |
} |
$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->ajouterCommentaire($station, $source, $maille); |
$this->appliquerStyleMaille($source, $maille); |
} |
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) { |
if ($maille->hasAttribute('class') && $maille->attributes->getNamedItem('class')->value != $source) { |
$maille->setAttribute('class', 'tout'); |
} elseif (!$maille->hasAttribute('class')) { |
$maille->setAttribute('class', $source); |
} |
} |
|
private function ajouterCommentaire($station, $source, & $maille) { |
$commentaires = array(); |
if ($maille->hasAttribute('title')) { |
$commentaires = explode("; ", $maille->attributes->getNamedItem('title')->value); |
} |
$commentaire = ucfirst($source)." : {$station['commune']}, "; |
if (strlen($station['date']) == 4) { |
$commentaire .= "en {$station['date']} par {$station['auteur']}"; |
} else { |
$date = preg_replace("/(\d{4})-(\d{2})-(\d{2})/", "$3/$2/$1", $station['date']); |
$commentaire .= "le {$date} par {$station['auteur']}"; |
} |
$commentaires[] = trim($commentaire); |
$maille->setAttribute('title', implode('; ', $commentaires)); |
} |
|
|
|
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); |
} |
|
} |
|
?> |