<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>GIS &#38; Chips &#187; PostgreSQL</title>
	<atom:link href="http://www.gisandchips.org/tag/postgresql/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.gisandchips.org</link>
	<description>Geografía útil para llevar</description>
	<lastBuildDate>Tue, 29 Nov 2011 10:38:56 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>La ciencia de los suelos (I). Creación de triángulos texturales directamente desde una Geodatabase.</title>
		<link>http://www.gisandchips.org/2010/09/08/la-ciencia-de-los-suelos-i-creacion-de-triangulos-texturales-directamente-desde-una-geodatabase/</link>
		<comments>http://www.gisandchips.org/2010/09/08/la-ciencia-de-los-suelos-i-creacion-de-triangulos-texturales-directamente-desde-una-geodatabase/#comments</comments>
		<pubDate>Wed, 08 Sep 2010 04:44:54 +0000</pubDate>
		<dc:creator>benizar</dc:creator>
				<category><![CDATA[Programación]]></category>
		<category><![CDATA[gráficas]]></category>
		<category><![CDATA[pl/R]]></category>
		<category><![CDATA[PostGIS]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[R]]></category>

		<guid isPermaLink="false">http://www.gisandchips.org/?p=1629</guid>
		<description><![CDATA[Llevo un tiempo ocupado pero ya es hora de enseñar en GIS&#38;Chips algunas de las demos que realicé para mi Trabajo Fin de Master (TFM) sobre SIG. En este artículo os muestro la demo nº2 que consiste en la creación de triángulos texturales directamente desde una Geodatabase que diseño y creo previamente dentro del TFM. [...]]]></description>
			<content:encoded><![CDATA[<p>Llevo un tiempo ocupado pero ya es hora de enseñar en GIS&amp;Chips algunas de las demos que realicé para mi Trabajo Fin de Master (TFM) sobre SIG.</p>
<p>En este artículo os muestro la demo nº2 que consiste en la creación de triángulos texturales directamente desde una <strong>Geodatabase </strong>que diseño y creo previamente dentro del TFM. Pero más adelante añadiré algunos comentarios de las otras demos.</p>
<div id="attachment_1630" class="wp-caption aligncenter" style="width: 277px"><a href="http://www.gisandchips.org/wp-content/clasificacion_textural.png"><img class="size-medium wp-image-1630" src="http://www.gisandchips.org/wp-content/clasificacion_textural-267x300.png" alt="" width="267" height="300" /></a><p class="wp-caption-text">Triángulo textural</p></div>
<h3><span id="more-1629"></span>El TFM</h3>
<p>Es interesante comentar que el TFM es una pequeña parte de otra investigación que estoy realizando en el contexto de la comarca de la Marina Baja (Alicante-España) y los datos que se muestra en las distintas demos son parte de un muestreo para entender mejor el potencial nutritivo de los suelos de la comarca.</p>
<p>El título del TFM es “Diseño de una base de datos geográfica orientada al estudio de los suelos”. Evidentemente, en el espacio de un TFM no cabía desarrollar toda la idea, que podría ser muy trabajosa para una sola persona, del mismo modo que aquí no cabe desarrollar todo el TFM ya que hay algunas partes que no tienen que ver con lo que queremos contar en G&amp;C.</p>
<p>Si entráis en la página principal del la Web de demostraciones podéis leer un poco más sobre la intención y contenidos del TFM ( <a href="http://www.gisandchips.org/demos/suelosTFM/">http://www.gisandchips.org/demos/suelosTFM/</a> ). Además en esta página se explican los detalles de la tecnología utilizada y del método de trabajo (<strong>PostgreSQL</strong>, <strong>PostGIS</strong>, R, <strong>pl/R</strong>&#8230;).</p>
<p>Considero que las demos 2 y 3 son más interesantes, puesto que la primera es solo una función de clasificación que cada uno podría hacer a su gusto, pero si a alguien le interesa la explicaré más adelante.</p>
<div id="attachment_1645" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.gisandchips.org/wp-content/tritex_1.jpg"><img class="size-medium wp-image-1645" src="http://www.gisandchips.org/wp-content/tritex_1-300x232.jpg" alt="" width="300" height="232" /></a><p class="wp-caption-text">Página de la Demo</p></div>
<h3>Los triángulos texturales</h3>
<p>El estudio de los suelos es una disciplina tremendamente amplia, por lo que aquí nos limitaremos a dar, de un modo más breve, las explicaciones necesarias para entender los gráficos resultantes.</p>
<p>Los <strong>triángulos texturales</strong> son gráficos que facilitan la interpretación de la granulometría del suelo. Así pues, habitualmente la textura del suelo se puede representar en un diagrama ternario. En dicho diagrama ternario se emplean reglas trigonométricas para representar en el plano coordenadas tridimensionales que se refieren a distintas combinaciones de clases granulométricas (clases texturales) cuya suma es constante (100). Por último, las clases texturales son convenientes para representar a la textura del suelo en mapas ya que resulta más sencillo representar una variable que no tres, y su uso es bastante amplio en descripciones y clasificaciones del suelo.</p>
<p>A pesar de todas las ventajas de estos gráficos, aparece la dificultad de que existen gran número de triángulos texturales que permiten la clasificación de los suelos, lo que implica que en caso de querer incluir herramientas relacionadas en una BDGS (Geodatabase de suelos) se deba considerar tal variedad de criterios. En este caso se ha creado un gráfico de texturas según las especificaciones del USDA (1951) en castellano.</p>
<p>Pese a que existe cierta variedad de programas pensados para la elaboración de los triángulos de texturas parece interesante que una BDGS que almacene los datos de textura de suelos sea capaz de generar este tipo de gráficos. Además, los otros software suelen ser difíciles de encontrar y poco flexibles. Aquí podemos modificar nuestro gráfico a placer.</p>
<div id="attachment_1643" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.gisandchips.org/wp-content/tritex_results.jpg"><img class="size-medium wp-image-1643" src="http://www.gisandchips.org/wp-content/tritex_results-300x188.jpg" alt="" width="300" height="188" /></a><p class="wp-caption-text">Página de resultados de la demo</p></div>
<h3>Demostración  Triángulo Textural</h3>
<p>En la propia página Web (<a href="http://www.gisandchips.org/demos/suelosTFM/paginas/demo_tritex1.php">http://www.gisandchips.org/demos/suelosTFM/paginas/demo_tritex1.php</a> ) se explica como interactuar con la demo, seleccionando las muestras que se desee, si se desea etiquetar las muestras y con que símbolo se van a representar. Como se puede ver, los datos han sido previamente ordenados según una consulta espacial usando funciones de <strong>PostGIS</strong>, por lo que la gráfica que vamos a generar se ve enriquecida por esta posibilidad. A partir de los datos seleccionados se ejecuta una función escrita en pl/R que usa la librería &#8220;Plotrix&#8221; de R para generar un triángulo textural personalizado y guardarlo como un fichero PNG en el servidor. La función que se usa en este ejemplo puede ser personalizada en muchos sentidos para obtener otros triángulos texturales (hay decenas), en otros idiomas, clasificando los símbolos por algún atributo de la base de datos&#8230;</p>
<p>El uso de la función resulta muy sencillo,</p>
<pre class="brush: sql; title: ; notranslate">
SELECT  _plr_clasif_textural ( 'arenas' , 'limos' , 'arcilla' , 'submuestra' , 'simbolo' , 'etiquetas') ;
</pre>
<p>y a continuación podemos ver el código que hemos usado para crearla, y algunos comentarios:</p>
<pre class="brush: sql; title: ; notranslate">
-- Function: _plr_clasif_textural(text, text, text, text, text, text)
-- DROP FUNCTION _plr_clasif_textural(text, text, text, text, text, text);
CREATE OR REPLACE FUNCTION _plr_clasif_textural(text, text, text, text, text, text)
RETURNS text AS
$BODY$
</pre>
<pre class="brush: bash; title: ; notranslate">
# Cargamos las librerias necesarias
library(Cairo)
library(plotrix)
# Definimos la funcion
clasif.textural = function (soiltexture = NULL, at = seq(0.1, 0.9, by = 0.1),
axis.labels = c(&quot;% arena (entre 0,05 y 2 mm)&quot;, &quot;% limo (entre 0,05 y 0,002 mm)&quot;, &quot;% arcilla (menor de 0,002  mm)&quot;),
tick.labels = list(l = seq(10, 90, by = 10), r = seq(10,
90, by = 10), b = seq(10, 90, by = 10)), show.names = TRUE,
show.lines = TRUE, col.names = &quot;black&quot;, bg.names = par(&quot;bg&quot;),
show.grid = TRUE, col.axis = &quot;black&quot;, col.lines = &quot;black&quot;,
col.grid = &quot;gray&quot;, lty.grid = 3, show.legend = FALSE, label.points = FALSE,
point.labels = '', col.symbols = &quot;blue&quot;, pch = par(&quot;pch&quot;),
...)
{
par(xpd = TRUE)
plot(0.5, type = &quot;n&quot;, axes = FALSE, xlim = c(0, 1), ylim = c(0,
1), main = NA, xlab = NA, ylab = NA)
triax.frame(at = at, axis.labels = axis.labels,
tick.labels = tick.labels, col.axis = col.axis, show.grid = show.grid,
col.grid = col.grid, lty.grid = lty.grid)
arrows(0.12, 0.41, 0.22, 0.57, length = 0.15)
arrows(0.78, 0.57, 0.88, 0.41, length = 0.15)
arrows(0.6, -0.1, 0.38, -0.1, length = 0.15)
if (show.lines) {
triax.segments &lt;- function(h1, h3, t1, t3, col) {
segments(1 - h1 - h3/2, h3 * sin(pi/3), 1 - t1 -
t3/2, t3 * sin(pi/3), col = col)
}
h1 &lt;- c(85, 70, 80, 52, 52, 50, 20, 8, 52, 45, 45, 65,
45, 20, 20)/100
h3 &lt;- c(0, 0, 20, 20, 7, 0, 0, 12, 20, 27, 27, 35, 40,
27, 40)/100
t1 &lt;- c(90, 85, 52, 52, 43, 23, 8, 0, 45, 0, 45, 45,
0, 20, 0)/100
t3 &lt;- c(10, 15, 20, 7, 7, 27, 12, 12, 27, 27, 55, 35,
40, 40, 60)/100
triax.segments(h1, h3, t1, t3, col.lines)
}
if (show.names) {
xpos &lt;- c(0.5, 0.7, 0.7, 0.73, 0.73, 0.5, 0.275, 0.275,
0.27, 0.27, 0.25, 0.135, 0.18, 0.07, 0.49, 0.72,
0.9)
ypos &lt;- c(0.66, 0.49, 0.44, 0.36, 0.32, 0.35, 0.43, 0.39,
0.3, 0.26, 0.13, 0.072, 0.032, 0.024, 0.18, 0.15,
0.06) * sin(pi/3)
snames &lt;- c(&quot;arcillosa&quot;, &quot;arcillosa&quot;, &quot;limosa&quot;, &quot;franco arcillosa&quot;, &quot;limosa&quot;,
&quot;franco arcillosa&quot;, &quot;arcillosa&quot;, &quot;arenosa&quot;, &quot;franco arcillosa&quot;, &quot;arenosa&quot;,
&quot;franco arenosa&quot;, &quot;arenosa&quot;, &quot;franca&quot;, &quot;arenosa&quot;, &quot;franca&quot;, &quot;franco limosa&quot;,
&quot;limosa&quot;)
boxed.labels(xpos, ypos, snames, border = FALSE, col = col.names,
cex=0.8, xpad = 0.5)
}
par(xpd = FALSE)
if (is.null(soiltexture))
return(NULL)
soilpoints &lt;- triax.points(soiltexture, show.legend = show.legend,
label.points = label.points, point.labels = point.labels,
col.symbols = col.symbols, pch = pch, ...)
invisible(soilpoints)
}
# Definimos la imagen
CairoPNG(&quot;…/images/clasificacion_textural.png&quot;, width=500, height=560)
# Construimos las consultas
select = 'select '
arena = paste(arg1, ',', sep=' ');
limo = paste(arg2, ',', sep=' ');
arcilla = paste(arg3, ' ');
from = ' from '
tabla = arg4
selection = paste(select, arena, limo, arcilla, from, tabla, sep='');
selectgids = paste('select gid', from, tabla, sep='');
# Ejecutamos las consultas
texturas &lt;- pg.spi.exec(selection)
gids&lt;- pg.spi.exec(selectgids)
# Ejecutamos la funcion creada mas arriba
soiltex.return&lt;-clasif.textural(texturas,
pch=arg5, point.labels = gids[,], label.points=arg6)
dev.off()
# Damos permisos de lectura
system('chmod go+r …/images/clasificacion_textural.png');
# Una comprobacion para asegurarnos de que se ha creado la grafica, pero no afecta para nada.
if (file.exists('…/images/clasificacion_textural.png')) {
print ('Grafico realizado. Se llama …/images/clasificacion_textural.png')};
</pre>
<pre class="brush: sql; title: ; notranslate">
$BODY$
LANGUAGE 'plr' VOLATILE
COST 100;
ALTER FUNCTION _plr_clasif_textural(text, text, text, text, text, text) OWNER TO postgres;
</pre>
<h3>Algunas notas sobre todo esto:</h3>
<p>(1) En el TFM se apunta que en breve aparecerá una librería creada por Julien Moeys ( <a href="https://r-forge.r-project.org/projects/soiltexture/">https://r-forge.r-project.org/projects/soiltexture/</a> ) que hará innecesario tener que crear la función por nosotros mismos como hemos hecho en esta demostración. Será interesante comentar con los miembros del proyecto la posibilidad de compartir las funciones de su proyecto en una Web completamente dedicada al cálculo de triángulos texturales, donde los usuarios puedan añadir sus propios datos.</p>
<p>(2) Los datos de ejemplo están un poco modificados pero se aproximan a la realidad.</p>
<p>(3) La función tiene muchos aspectos mejorables, por lo menos en cuanto a la legibilidad. Otra posibilidad sería la de que no todos los argumentos de entrada fuesen de tipo texto. Esto lo veremos plasmado en el código de la demo 3.</p>
<p>(4) Si en la página  inicial de la demo no se ve una lista con las muestras disponibles (como en la segunda imagen) será porqué el servidor de la base de datos ha caído y lo deberemos reiniciar en breve. Solo ha pasado una vez, pero quien sabe…</p>
<p>(5) Este artículo destaca la potencia de pl/R a la hora de crear gráficos de lo más complejos.</p>
<h3>Agradecimientos:</h3>
<p>El TFM de que he estado hablando ha sido dirigido por Toni Hernández, en el Máster en Sistemas de Información Geográfica y Teledetección de la Universitat de Girona (UNIGIS), y fue presentado en Mayo de 2010. Les estoy muy agradecido a todos los miembros, tanto alumnos como profesores, por estos últimos años disfrutando y aprendiendo SIG.</p>
<p>Especialmente, quiero agradecer a los compañeros de G&amp;C por la ayuda con instalaciones, creación de la Web y otros dolores de cabeza.</p>
<p>——————————————————————</p>
<p>Si queréis contactar podéis enviarme un email (asunto: gisandchips):</p>
<p>Benito M. Zaragozí</p>
<p>benito.zaragozi@ua.es</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gisandchips.org/2010/09/08/la-ciencia-de-los-suelos-i-creacion-de-triangulos-texturales-directamente-desde-una-geodatabase/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cómo evitar la inserción de geometrías duplicadas en PostgreSQL</title>
		<link>http://www.gisandchips.org/2009/12/22/como-evitar-la-insercion-de-geometrias-duplicadas-en-postgresql/</link>
		<comments>http://www.gisandchips.org/2009/12/22/como-evitar-la-insercion-de-geometrias-duplicadas-en-postgresql/#comments</comments>
		<pubDate>Tue, 22 Dec 2009 11:51:02 +0000</pubDate>
		<dc:creator>josetomas</dc:creator>
				<category><![CDATA[Consejo práctico]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[geometrías duplicadas]]></category>
		<category><![CDATA[PostGIS]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[RULE]]></category>

		<guid isPermaLink="false">http://www.gisandchips.org/?p=1171</guid>
		<description><![CDATA[Una de las tareas habituales en el tratamiento de inconsistencias cartográficas es la detección y corrección de geometrías duplicadas. En muchos casos eliminarlas es necesario para evitar incoherencias en nuestra base de datos geográfica, sobre todo en cuanto al cómputo de frecuencias, longitudes y superficies. Por otra parte la eliminación a posteriori, también plantea problemas [...]]]></description>
			<content:encoded><![CDATA[<p>Una de las tareas habituales en el tratamiento de inconsistencias cartográficas es la detección y corrección de geometrías duplicadas. En muchos casos eliminarlas es necesario para evitar incoherencias en nuestra base de datos geográfica, sobre todo en cuanto al cómputo de frecuencias, longitudes y superficies. Por otra parte la eliminación a posteriori, también plantea problemas de decisión que pueden complicar el código a desarrollar y desembocar en tiempos dilatados de proceso. De modo que, en ocasiones merece la pena plantearse la detección de geometrías duplicadas a priori. Implementar semejante mecanismo de control del lado del cliente puede resultar relativamente sencillo, pero lo que aquí os propongo es centralizar la lógica y evitar la inserción de geometrías duplicadas desde el lado del servidor PostgreSQL/PostGIS.<span id="more-1171"></span></p>
<p>Planteado el problema, la primera solución que viene a la mente pasa por un &#8220;trigger&#8221; que haga la llamada a la correspondiente función de evaluación y lance un mensaje de error en caso necesario. Sin embargo, si lanzar el mensaje de error no es absolutamente necesario y lo que perseguimos es que una transacción de, por ejemplo, 1000 geometrías donde 50 son duplicadas, se complete con los 950 registros válidos insertados, entonces podemos usar una regla o <a title="RULE" href="http://www.postgresql.org/docs/8.4/static/rules.html" target="_blank">RULE</a>. Cada dos por tres estoy revisitando el sistema de reglas de PostgreSQL y no deja de sorprenderme por su versatilidad y elegancia. Echad un vistazo a la solución propuesta y decidid por vosotros mismos:</p>
<pre class="brush: sql; title: ; notranslate">
CREATE OR REPLACE RULE skip_duplicate AS
 ON INSERT TO table_name
 WHERE 0 != (SELECT count(*)
 FROM table_name
 WHERE geom_field ~= new.geom_field) DO INSTEAD NOTHING;
</pre>
<p>Como podéis comprobar, hay 2 claves para interpretar esta regla:</p>
<p>1) Es una regla condicional (CREATE RULE &#8230; <em>WHERE</em> &#8230; DO &#8230;), y en la condición integramos una subquery que emplea el operador de igualdad geométrica (<em>~=</em>) para evaluar si la geometría de entrada (<em>new.geom_field</em>) es un duplicado. Recordad que, para acelerar el proceso, los operadores de PostGIS explotan, si está presente, el índice GIST sobre el campo de geometría.</p>
<p>2) Con <em>INSTEAD NOTHING</em> indicamos al motor de reescritura de expresiones subyacente al sistema de reglas que, cuando se cumpla la condición anterior, simplemente vacíe la expresión entrante y no haga nada. Por tanto, la sentencia INSERT se omite y deja de formar parte de la transacción actual.</p>
<p>¡Eso es todo!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gisandchips.org/2009/12/22/como-evitar-la-insercion-de-geometrias-duplicadas-en-postgresql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Uso de &#8220;dissolve&#8221; con POSTGIS</title>
		<link>http://www.gisandchips.org/2009/12/17/uso-de-dissolve-con-postgis/</link>
		<comments>http://www.gisandchips.org/2009/12/17/uso-de-dissolve-con-postgis/#comments</comments>
		<pubDate>Thu, 17 Dec 2009 10:36:51 +0000</pubDate>
		<dc:creator>Miguel</dc:creator>
				<category><![CDATA[Consejo práctico]]></category>
		<category><![CDATA[dissolve]]></category>
		<category><![CDATA[PostGIS]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://www.gisandchips.org/?p=1110</guid>
		<description><![CDATA[Uno de los problemas que tuve al manejar los datos geométricos del INE fue que la capa de municipios constaba de geometría de tipo POLYGON. Lo que necesitaba conseguir era agrupar esa geometría simple y convertirla en MULTIPOLYGON. Eso me dio la idea para el siguiente consejo práctico. Para ello una simple ojeada a la [...]]]></description>
			<content:encoded><![CDATA[<p>Uno de los problemas que tuve al manejar los datos geométricos del INE fue que la capa de municipios constaba de geometría de tipo POLYGON. Lo que necesitaba conseguir era agrupar esa geometría simple y convertirla en MULTIPOLYGON. Eso me dio la idea para el siguiente consejo práctico.</p>
<p>Para ello una simple ojeada a la documentación de <a href="http://postgis.refractions.net/documentation/manual-1.4/">POSTGIS</a> y encontré la función que necesitaba, <strong><a href="http://postgis.refractions.net/documentation/manual-1.4/ST_Union.html">st_union</a></strong>. Esta función nos une la geometría en función de un atributo seleccionado.</p>
<p>Voy a mostrar un ejemplo sencillo, pero muy pedagógico.  En este ejemplo partimos de tres polígonos simples,  su geometría es de tipo POLYGON y quiero unirlos por un atributo común, en su caso el código.</p>
<p><img class="alignnone size-full wp-image-1127" src="http://www.gisandchips.org/wp-content/polygon.PNG" alt="poligonos" width="417" height="313" /><br />
<span id="more-1110"></span><br />
Vemos en la imagen anterior los 3 polígonos, dos de los cuales tienen el mismo atributo (campo código).</p>
<p>La SQL quedaría de la siguiente manera:</p>
<pre class="brush: sql; title: ; notranslate">select st_union(geometria) from poligonos group by codigo;</pre>
<p>El problema viene con el resultado de esa consulta, y es la heterogeneidad del tipo de geometría:</p>
<p><img class="alignnone size-full wp-image-1133" src="http://www.gisandchips.org/wp-content/stunion.PNG" alt="stunion" width="467" height="58" /></p>
<p>Para que eso no ocurra, añadimos la función<strong> <a href="http://postgis.refractions.net/documentation/manual-1.4/ST_Multi.html">st_multi</a></strong>, y conseguimos una homogeneidad del tipo de geometría, convirtiendo todas las geometrías en MULTIPOLYGON:</p>
<pre class="brush: sql; title: ; notranslate">select st_multi(st_union(geometria)) from poligonos group by codigo;</pre>
<p><img class="alignnone size-full wp-image-1135" src="http://www.gisandchips.org/wp-content/stmultiunion.PNG" alt="stmultiunion" width="478" height="55" /></p>
<p>En caso de que los polígonos sean adyacentes, pasaría a ser un único polígono, es decir,  elimina la frontera entre ambos.</p>
<p><img class="alignnone size-full wp-image-1142" src="http://www.gisandchips.org/wp-content/polygon21.PNG" alt="polygon2" width="479" height="485" /></p>
<p>Ahora comprobamos que al usar <strong>st_union</strong>, simplemente nos ha creado un polígono a partir de un atributo común, manteniendo la geometría de tipo POLYGON y en este caso ya no hace falta usar st_multi.</p>
<p><img class="alignnone size-full wp-image-1140" src="http://www.gisandchips.org/wp-content/stunion2.PNG" alt="stunion2" width="470" height="54" /><!--more--></p>
]]></content:encoded>
			<wfw:commentRss>http://www.gisandchips.org/2009/12/17/uso-de-dissolve-con-postgis/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Creación de un mapa sensible utilizando Pl/PgSQL y PHP_Mapscript</title>
		<link>http://www.gisandchips.org/2009/11/06/creacion-de-un-mapa-sensible-utilizando-plpgsql-y-php_mapscript/</link>
		<comments>http://www.gisandchips.org/2009/11/06/creacion-de-un-mapa-sensible-utilizando-plpgsql-y-php_mapscript/#comments</comments>
		<pubDate>Fri, 06 Nov 2009 17:46:56 +0000</pubDate>
		<dc:creator>Miguel</dc:creator>
				<category><![CDATA[Programación]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[mapa]]></category>
		<category><![CDATA[mapscript]]></category>
		<category><![CDATA[mapserver]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[php_mapscript]]></category>
		<category><![CDATA[Pl/pgsql]]></category>
		<category><![CDATA[PostGIS]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[programación]]></category>

		<guid isPermaLink="false">http://www.gisandchips.org/?p=942</guid>
		<description><![CDATA[El objetivo no es otro que convertir nuestro mapa en algo más interactivo para el usuario, dando más información que la meramente visual. El siguiente artículo, muestra el camino para alcanzar nuestra meta,  seguramente no sea la única ni la mejor, pero nos será útil para nuestro fín. Obviaremos la construcción del mapfile, ya que [...]]]></description>
			<content:encoded><![CDATA[<p>El objetivo no es otro que convertir nuestro mapa en algo más interactivo para el usuario, dando más información que la meramente visual. El siguiente artículo, muestra el camino para alcanzar nuestra meta,  seguramente no sea la única ni la mejor, pero nos será útil para nuestro fín.</p>
<p>Obviaremos la construcción del mapfile, ya que fue abordado en otro <a href="http://www.gisandchips.org/2009/11/02/creacion-de-un-mapfile-de-forma-dinamica-al-vuelo/">artículo</a>, pero trabajaremos a partir de ese código.</p>
<p>Lo primero que necesitamos hacer es preparar la función en lenguaje PL/pgSQL que nos devolverá las coordenadas de los vértices que componen cada uno de los polígonos a partir de un parámetro, que en nuestro caso será el código municipal, y posteriormente se hará la conversión de esos vértices de metros a pixel con PHP.<span id="more-942"></span></p>
<pre class="brush: sql; title: ; notranslate">
CREATE OR REPLACE FUNCTION gc_listvertices(cod_municipal character varying)
RETURNS SETOF record AS
$BODY$
DECLARE
countpol bigint;
polygon geometry;
perimeter geometry;
countpoints integer;
i integer;
j integer;
point record;
BEGIN
--Teniendo en cuenta que cada municipio puede estar compuesto de varios polígonos, primero hacemos un conteo de los polígonos de cada municipio
select into countpol count(*) from (select st_dump(geometria) from municipios where codmun= cod_municipal) foo;
for j in 1..countpol loop
--Por cada municipio, nos devolverá los polígonos descompuestos. La función st_dump, lo que nos devuelve es tantas filas como polígonos contiene el municipio en cuestión, es decir nos descompone el MULTIPOLYGON en un array que contiene un único POLYGON
select into polygon geom from (select (st_dump(geometria)).path, (st_dump(geometria)).geom from municipios where codmun = cod_municipal) foo where path[1] = j;
--La función st_exteriorring nos devuelve un LINESTRING, que representa el anillo exterior del polígono dado.
--ATENCIÓN: esta función no trabaja con MULTIPOLYGON, de ahí la descomposición anterior
select into perimeter st_exteriorring(polygon);
--Contamos el número de vértices que componen el POLYGON
select into countpoints st_npoints(polygon);
for i in 1..countpoints loop
--Por último, nos guardamos en una variable, la coordenada X y la coordenada Y de cada vértice.
--ATENCIÓN: puesto que nos devuelve indiscriminadamente las coordenadas de todos los vértices de todos los polígonos que componen el municipio, se ha añadido un campo booleano que nos devuelve true en caso de ser un vértice final.
select into point st_x(st_pointn(perimeter, i)), st_y(st_pointn(perimeter, i)), (i=countpoints) as tend;
return next point;
end loop;
end loop;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE
COST 100
ROWS 1000;
ALTER FUNCTION gc_listvertices(character varying) OWNER TO postgres;</pre>
<p>Ahora sólo queda hacer la conversión con PHP:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php header('Content-Type: text/html; charset=UTF-8'); ?&gt;
&lt;html&gt;
&lt;head&gt;
&lt;title&gt;Ejemplo de mapa sensible&lt;/title&gt;
&lt;style type=&quot;text/css&quot;&gt;
.munInfo{
border: 1px solid #C0C0C0;
background-color: white;
border-bottom-width: 0;
width: 170px;
height: 70px;
position: absolute;
}
&lt;/style&gt;

&lt;script&gt;
function info(nombre,area)
{
        document.getElementById('munInfo').innerHTML = &quot;Municipio=&quot;  + nombre +&quot; &lt;br&gt; Area =&quot; + area +&quot; km2&quot;;
}
&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;?php
//Este código es el usado en un artículo anterior, pero para hacer más fluido el ejemplo, sólo se han seleccionado los municipios de la Comunidad Valenciana. Lo ideal es automatizar tanto la extensión máxima de la caja de la geometría como su equivalencia en el tamaño en pixeles del mapa. Para hacer el ejemplo más fluido se añaden estos parámetros a mano.
dl('php_mapscript.so');
$Map=ms_newMapObj(&quot;&quot;);
$Map-&gt;set(&quot;name&quot;,&quot;Mapa&quot;);
//Equivalencia en pixeles del tamaño del mapa
$Map-&gt;setSize(432,750);
//Extensión de la caja para los municipios de la Comunidad Valenciana
$Map-&gt;setExtent(626680,4191059,815673.125,4519371);
$Map-&gt;web-&gt;set(&quot;imagepath&quot;,&quot;/tmp&quot;);
$Map-&gt;web-&gt;set(&quot;imageurl&quot;,&quot;/ms_tmp&quot;);
$Layer2=ms_newLayerObj($Map);
$Layer2-&gt;set(&quot;name&quot;,&quot;Municipios&quot;);
$Layer2-&gt;set(&quot;type&quot;,MS_LAYER_POLYGON);
$status = $Layer2-&gt;set(&quot;status&quot;,MS_ON);
$Layer2-&gt;setConnectionType(MS_POSTGIS);
$Layer2-&gt;set(&quot;connection&quot;,&quot;user=****** dbname=demos host=localhost&quot;);
//La consulta ha sido modificada con respecto a la original, para mostrar sólo los municipios de la Comunidad Valenciana
$Layer2-&gt;set(&quot;data&quot;,&quot;geometria from (select geometria,gid from  ine.municipios where com = '10') as foo  using unique gid using srid=23030&quot;);
$clase = ms_newClassObj($Layer2);
$estilo = ms_newStyleObj($clase);
$estilo-&gt;color-&gt;setRGB(217,233,107);
$estilo-&gt;outlinecolor-&gt;setRGB(0,0,0);
$Image=$Map-&gt;Draw();
$url_imagen=$Image-&gt;saveWebImage();
//Añadimos que la imagen será usada como un mapa de html
echo &quot;&lt;img src=&quot;.$url_imagen.&quot; usemap='#sensible'&gt;&quot;;
echo &quot;&lt;map name='sensible'&gt;&quot;;

//Lo siguiente, es conectarse a la base de datos para consultar los municipios que vamos a mostrar en el mapa
$conn = pg_connect(&quot;host=localhost port=5432 dbname=demos user=****** password=******&quot;);
$sqlmun= &quot;select nombre04 as nombre,codmun as codmunicipal, area(geometria) as area from ine.municipios where com = '10'&quot;;
$poligono = pg_query($conn,$sqlmun);
$rowspol=pg_num_rows($poligono);
for ($h=0; $h&lt;$rowspol; $h++)
{
        $arraypol=pg_fetch_array($poligono,$h);
        $nombre=$arraypol['nombre'];
        $codmun=$arraypol['codmunicipal'];
        $area=round(($arraypol['area']/1000000),2);

        $pxmin = 626680;
        $pymin = 4191059;
        $pxmax = 815673.125;
        $pymax = 4519371;

        //distancia en metros de los ejes
        $eqx=$pxmax-$pxmin;
        $eqy=$pymax-$pymin;
//Llegados a este punto ejecutamos la función anterior que creamos en la base de datos, para que nos devuelva las coordenadas de los vértices de cada uno de los polígonos
        $sqlpolcoords=&quot;select * from ine.gc_listvertices('$codmun') as foo(x float, y float,tend boolean)&quot;;
        $polcoords= pg_query($conn,$sqlpolcoords);
        $rowspolcoords=pg_num_rows($polcoords);
        for ($j=0; $j&lt;$rowspolcoords; $j++)
        {
//Obtenemos los tres parámetros por separado que nos devuelve la función y hacemos la conversión de metros a pixel. Como he comentado anteriormente lo ideal es que esto se realice de manera automatizada, sin que introduzcamos nosotros la anchura y la altura del mapa
                $arraypolcoords=pg_fetch_array($polcoords,$j);
                $x=$arraypolcoords['x'];
                $y=$arraypolcoords['y'];
                $tend=$arraypolcoords['tend'];
                $xcal=$x-$pxmin;
                $ycal=$pymax-$y;

                $resx=round(((432*$xcal)/$eqx),0);
                $resy=round(((750*$ycal)/$eqy),0);
                $coordenadas.=$resx.&quot;,&quot;.$resy.&quot;,&quot;;
//Lo que va a hacer este parámetro es cortar cada polígono cada vez que devuelva true, de manera que en el caso de Alicante que son cuatro polígonos, los separa cada uno en un área distinta
                if($tend=='t')
                {
                        echo&quot;&lt;area shape=poly coords='$coordenadas' href=\&quot;javascript:void(0);\&quot; onClick=\&quot;munInfo('$nombre','$area');\&quot; alt='$nombre'&gt;\n&quot;;
//Para el ejemplo he creado una simple función en javascript que nos muestre el nombre y el área en un div cuando pasemos el ratón por encima de cualquier municipio.
                        $coordenadas=&quot;&quot;;
                }
        }
}
echo&quot;&lt;/map&gt;&quot;;
?&gt;
&lt;div id=&quot;munInfo&quot; class=&quot;munInfo&quot;&gt;&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>El resultado del ejemplo será este <a href="http://www.gisandchips.org/demos/mapscript/index_sense.php">mapa sensible</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gisandchips.org/2009/11/06/creacion-de-un-mapa-sensible-utilizando-plpgsql-y-php_mapscript/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Aumentar velocidad de carga de un mapfile utilizando simplificación de geometrías</title>
		<link>http://www.gisandchips.org/2009/11/05/aumentar-velocidad-de-carga-de-un-mapfile-utilizando-simplificacion-de-geometrias/</link>
		<comments>http://www.gisandchips.org/2009/11/05/aumentar-velocidad-de-carga-de-un-mapfile-utilizando-simplificacion-de-geometrias/#comments</comments>
		<pubDate>Thu, 05 Nov 2009 11:48:58 +0000</pubDate>
		<dc:creator>pepe</dc:creator>
				<category><![CDATA[Comparativa]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[geometry simplification]]></category>
		<category><![CDATA[mapfile]]></category>
		<category><![CDATA[mapscript]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[PostGIS]]></category>
		<category><![CDATA[PostgreSQL]]></category>

		<guid isPermaLink="false">http://www.gisandchips.org/?p=492</guid>
		<description><![CDATA[En el anterior post creamos un mapfile dinámicamente con PHPMapScript, ahora lo que vamos a ver es como conseguir que la velocidad de carga de este mapfile se reduzca de forma considerable utilizando simplificación de geometrías mediante una función en PostGIS, esperando obtener un mapa con los municipios de toda España. Resultado esperado: El código [...]]]></description>
			<content:encoded><![CDATA[<p>En el anterior <a href="http://www.gisandchips.org/2009/11/02/creacion-de-un-mapfile-de-forma-dinamica-al-vuelo/" target="_blank">post</a> creamos un mapfile dinámicamente con PHPMapScript, ahora lo que vamos a ver es como conseguir que la velocidad de carga de este mapfile se reduzca de forma considerable utilizando simplificación de geometrías mediante una función en PostGIS, esperando obtener un mapa con los municipios de toda España.</p>
<p style="text-align: center;">Resultado esperado:<img class="aligncenter size-full wp-image-1082" title="4b024cb4_7df_1" src="http://www.gisandchips.org/wp-content/4b024cb4_7df_1.gif" alt="Mapa simplificado" width="300" height="300" /></p>
<p style="text-align: center;">
<p>El código de generación del mapfile será el mismo que en el  <a href="http://www.gisandchips.org/2009/11/02/creacion-de-un-mapfile-de-forma-dinamica-al-vuelo/" target="_blank">post</a> de creación del mapfile &#8220;al vuelo&#8221;, tan solo habría que cambiar la forma de obtener los datos, para que en lugar de obtenerlos con una simple sentencia sql, llamar a una función que obtuviera las geometrías simplificadas a costa de perder nivel de detalle (inapreciable a la vista).</p>
<p><span id="more-492"></span></p>
<p>Cuando se trata de simplificar geometrías hay que tener en cuenta la dimensión del mapa que queremos obtener para en función de esta dimensión, poder obtener de alguna forma un coeficiente de simplificación que se adecue a la simplificación que pretendemos obtener (es decir, ni que no nos haga casi simplificación, ni que simplifique demasiado).</p>
<p>Para obtener este factor de simplificación, podemos hacer varias operaciones, en este caso realizaremos una operación como la siguiente, dividiremos el resultado de restar a la xmax la xmin de la entensión de la geometria entre el ancho del mapa que queremos obtener.</p>
<p>Es decir, obtenemos la extensión de la geometría que estamos analizando , sacamos al xmax y la xmin, las restamos y el resultado lo dividimos entre el ancho del mapa que queremos obtener:</p>
<p>(xmax(extent(geometria) )- xmin(extent(geometria)))/Ancho del mapa</p>
<p>Creamos una función en sql para obtener el factor de simplificación que deseamos:</p>
<pre class="brush: php; title: ; notranslate">
create or replace function fs(float8) returns float8 AS $$
 select (xmax(extent(geometria))-xmin(extent(geometria)))/$1 from ine.municipios;
$$ LANGUAGE SQL;
</pre>
<p>Una vez que tenemos el factor de simplificación obtenido con la función anterior, ya podemos aplicar la simplificación con el factor de simplificación obtenido anteriormente.</p>
<p>Podemos hacer una comparativa del aumento de velocidad entre realizar una consulta sin simplificación y otra con la simplificación, por ejemplo para un mapa bastante grande de 4000px.</p>
<p>1ª consulta: &#8220;<strong><em>select geometria  from municipios2</em></strong>&#8221;</p>
<p>2ª consulta:&#8221;<strong><em>select st_simplify(geometria,factor_simplificacion) from municipios2</em></strong>&#8221;</p>
<p>En PostgreSQL, al ejecutar las dos sentencias podemos comparar y obtener:</p>
<p>1ª consulta</p>
<ul>
<li>Tiempo de ejecución de la consulta: <strong>50,84 segundos</strong></li>
<li>Numero de vertices: <strong>393666</strong></li>
</ul>
<p>2ª consulta</p>
<ul>
<li>Tiempo de ejecución de la consulta: <strong>19,51 segundos</strong></li>
<li>Numero de vertices: <strong>141610</strong></li>
</ul>
<p>De esta manera comprobamos que se produce un aumento en la velocidad a cambio de reducir el nivel de detalle, circunstancia que nos viene bien de cara a la publicación web, ya que no necesitamos un nivel de detalle elevado.</p>
<p>Para constaruir ahora la layer en MapScript, la sentencia SQL para obtener los datos sería como esta:</p>
<pre class="brush: php; title: ; notranslate">
$name = $Layer2-&gt;set(&quot;name&quot;,&quot;Municipios&quot;);
$type = $Layer2-&gt;set(&quot;type&quot;,MS_LAYER_POLYGON);
$status = $Layer2-&gt;set(&quot;status&quot;,MS_ON);
//Conexión con nuestra base de datos que va as er de tipo POSTGIS
$Layer2-&gt;setConnectionType(MS_POSTGIS);
//Cadena de conexión a la base de datos donde tenemos nuestros datos

//En primer lugar, debemos obtener el factor de simplificación que obtenemos mediante consulta a postgresql desde php:
$conexion = pg_pconnect(&quot;host=localhost port=5432 dbname=demos user=postgres&quot;);

$sql=&quot;select fs(&quot;.$Map-&gt;width.&quot;)&quot;;
$resultado=pg_exec($conexion,$sql);
$factor=pg_result($resultado,0,0);

$Layer2-&gt;set(&quot;connection&quot;,&quot;user=postgres dbname=demos host=localhost&quot;);
//Filtro en sql que vamos a introducir para sacar nuestros datos a mostrar, aplicando el factor obtenido anteriormente
$data=&quot;geometria from (select st_simplify(geometria,&quot;.$factor.&quot;) as geometria, nombre,provincia,gid from municipios) as foo using SRID=23030, using unique gid&quot;;
$Layer2-&gt;set(&quot;data&quot;,$data);
//Una vez definida la estructura d ela capa procedemos a definir el estilo de nuestra capa número 1
</pre>
<p>Para la comparación de velocidad de creación de un mapfile con una única capa PostGIS utilizando una sentencia SQL normal y utilizando simplificación de geometrías, utilizando para ello varios test de medición de velocidad de carga, asumimos que vamos a crear un mapa bastante grande de una dimensión de 2000&#215;2000 pixeles.</p>
<p><a href="http://www.gisandchips.org/demos/mapscript/index_norm.php" target="_blank">Sin simplificación de geometrías </a>(tal y como se hizo en el artículo anterior, pero con una sola capa y de tamaño 2000&#215;2000 píxeles)</p>
<p><a href="http://www.gisandchips.org/demos/mapscript/index_simp.php" target="_blank">Con simplificación de geometrías</a> (utilizando la función que hemos programado anteriormente)</p>
<p>Para realizar la comparativa de cargas he utilizado la herramienta <a href="http://www.websitegoodies.com/tools/speed-test.php" target="_blank">Speed-Test </a></p>
<p>El resultado que he obtenido es el siguiente:<br />
(no se aprecia mucha diferencia, pero es debido a que se ha guardado en la caché y no es significativa la diferencia)<br />
- Con la sentencia normal (sin simplificación)</p>
<table style="border: 1px solid #cccccc;" border="0">
<tbody>
<tr>
<td style="padding: 0pt 5px;"><strong>URL:</strong></td>
<td style="padding: 0pt 5px;">http://www.gisandchips.org/demos/mapscript/index_norm.php</td>
</tr>
<tr>
<td style="padding: 0pt 5px;"><strong>Load Time:</strong></td>
<td style="padding: 0pt 5px;">1.048 seconds</td>
</tr>
<tr>
<td style="padding: 0pt 5px;"><strong>Page Size:</strong></td>
<td style="padding: 0pt 5px;">0.19 kb</td>
</tr>
</tbody>
</table>
<p>- Utilizando el factor de simplificación y realizando una simplificación de las geometrías:</p>
<table style="border: 1px solid #cccccc;" border="0">
<tbody>
<tr>
<td style="padding: 0pt 5px;"><strong>URL:</strong></td>
<td style="padding: 0pt 5px;">http://www.gisandchips.org/demos/mapscript/index_simp.php</td>
</tr>
<tr>
<td style="padding: 0pt 5px;"><strong>Load Time:</strong></td>
<td style="padding: 0pt 5px;">1.013 seconds</td>
</tr>
<tr>
<td style="padding: 0pt 5px;"><strong>Page Size:</strong></td>
<td style="padding: 0pt 5px;">0.18 kb</td>
</tr>
</tbody>
</table>
]]></content:encoded>
			<wfw:commentRss>http://www.gisandchips.org/2009/11/05/aumentar-velocidad-de-carga-de-un-mapfile-utilizando-simplificacion-de-geometrias/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Integración de R en PostgreSQL. Mi primera función en pl/R.</title>
		<link>http://www.gisandchips.org/2009/09/24/integracion-de-r-en-postgresql-mi-primera-funcion-en-plr/</link>
		<comments>http://www.gisandchips.org/2009/09/24/integracion-de-r-en-postgresql-mi-primera-funcion-en-plr/#comments</comments>
		<pubDate>Thu, 24 Sep 2009 08:49:58 +0000</pubDate>
		<dc:creator>benizar</dc:creator>
				<category><![CDATA[Análisis]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[pl/R]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[R]]></category>

		<guid isPermaLink="false">http://www.gisandchips.org/?p=165</guid>
		<description><![CDATA[En primer lugar, y para que ninguno de vosotros tenga impresión que no voy a hablar nunca de GIS, me gustaría tranquilizaros, y recordaros que en próximos artículos, yo o a quien le apetezca participar en este hilo, pasaremos a comentar usos de todo esto que estamos viendo orientado al tratamiento de la información espacial. [...]]]></description>
			<content:encoded><![CDATA[<p>En primer lugar, y para que ninguno de vosotros tenga impresión que no voy a hablar nunca de GIS, me gustaría tranquilizaros, y recordaros que en próximos artículos, yo o a quien le apetezca participar en este hilo, pasaremos a comentar usos de todo esto que estamos viendo orientado al tratamiento de la información espacial. Si hay alguien que quiera compartir sus experiencias con temas de R será bien recibido.</p>
<p>Este segundo artículo sobre tecnologías útiles para explotar toda la potencia de R se centra en el uso de R desde el PostgreSQL.</p>
<p>Como todos sabéis, tradicionalmente los Sistemas Gestores de Bases de Datos (SGBD), como PostgreSQL, Oracle, MySQL o Access han sido diseñados para guardar y gestionar gran cantidad de datos, por ello las posibilidades de análisis y salidas gráficas se han delegado mayormente en otros softwares como hojas de cálculo, paquetes estadísticos como SPSS, R o en nuestro caso en softwares SIG&#8230; pero eso se acabó  <img src='http://www.gisandchips.org/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />   .</p>
<p>pl/R es un lenguaje de programación procedural que permite contar con toda la potencia de cálculo y salidas gráficas del paquete estadístico R, así como de su lenguaje de programación desde dentro de funciones de PostgreSQL.</p>
<p><span id="more-165"></span></p>
<p>Los <span style="text-decoration: underline">requisitos básicos</span> para comenzar a trabajar con pl/R son, como no, tener instalado PostgreSQL (he trabajado sin demasiados problemas con las versiones 8.2 y 8.3), tener pl/R instalado, y crear una base de datos en PostgreSQL donde añadimos el nuevo lenguaje procedural.</p>
<p>Todo lo que necesitamos para iniciarnos lo podemos encontrar en la página WEB del creador de pl/R, <strong>Joe Conway</strong> (<a href="http://www.joeconway.com/plr/">http://www.joeconway.com/plr/</a> ), donde nos descargaremos los ficheros para la instalación tanto para Windows como para Linux. También hay documentación para dar los primeros pasos y unos cuantos más. Esta presentación os ayudará bastante (<a href="http://www.joeconway.com/oscon-pres-2003-1.pdf">http://www.joeconway.com/oscon-pres-2003-1.pdf</a> ). Os recomiendo leer todo lo que podáis, incluso su Curriculum que está en la página principal no tiene desperdicio.</p>
<p>Hay mucha documentación en Internet y ejemplos de funciones básicas. Nosotros para trabajar con algo que ya conocemos, volveremos a utilizar la función hist() de R para obtener el histograma de cualquier campo numérico que podamos tener en una tabla de nuestra base de datos.</p>
<p>Cualquiera que haya trabajado bien con R, bien con funciones de PostgreSQL en general encontrará rápidamente los primeros problemas o desventajas, si es que se pueden llamar así, de usar pl/R. En cualquiera de los dos casos, normalmente tendremos que aprender a usar una nueva herramienta (PostgreSQL o R), lo cual es un nuevo mundo. Depurar las funciones de pl/R puede ser engorroso si se hace directamente, y normalmente los procesos serán más lentos, proporcionalmente, que si trabajásemos solamente en uno de los dos lados del espejo.  Pero ahora os diré las ventajas que puedo destacar más rápidamente:</p>
<ul>
<li>Podemos ejecutar nuestras nuevas funciones mediante una      sencilla expresión de SQL,</li>
<li>las funciones estarán siempre junto con los datos      (acabando con la importación-exportación),</li>
<li>tenemos la posibilidad de usar las funciones desde PHP      y</li>
<li>un potente SGBD se encargará de gestionar el manejo de      los datos, lo cual es muy bueno cuando se trabaja con grandes volúmenes de      información.</li>
</ul>
<p>Hay más ventajas, pero creo que para empezar no está nada mal.</p>
<h3>Mi primera función en pl/R</h3>
<p>Una vez lo tenemos todo instalado, os recomiendo empezar probando que todo funciona bien desde el GUI de R, ya que desde pl/R nos será más complicada la depuración.</p>
<p>La función que paso a detallar está pensada para usarla en local y que la probéis con vuestros propios datos (numéricos; si no lo son veréis un mensaje de error). Se trata de crear un histograma y guardarlo como imagen.</p>
<p>Como os podéis dar cuenta parece una función de pl/pgSQL solo que cambiamos el lenguaje al final y metemos directamente código de R entre $BODYs o comillas simples, aunque resulta más práctico el $ por si dentro de la función necesitamos usar comillas de dos tipos.</p>
<p>Los comentarios de la función pueden ir con # igual que en R.</p>
<p>A continuación tenemos el código para crear la nueva función:</p>
<pre class="brush: sql; title: ; notranslate">

CREATE OR REPLACE FUNCTION _plr_hist(text, text)
RETURNS text AS
$BODY$
select = 'select '
campo = arg1
from = ' from '
tabla = arg2
selection = paste(select, campo, from, tabla, sep='');

## Ejecutamos la consulta y la almacenamos en el objeto &quot;sql&quot;;
sql &lt;- pg.spi.exec (selection);

## Lo que obtengamos a partir de aquí se imprimirá en un pdf...
dir='c:/temp/';
nam= arg1;
ext='.png';
newfile=paste(dir,nam,ext, sep='')
png(newfile);

hist(sql[,1], xlab = campo, ylab='frecuencias', main= campo, col='blue', ylim=c(0,20));

## Hasta aquí
dev.off();

## Si trabajamos en linux querremos hacer algo como lo siguiente
## para asignar privilegios de lectura a todos los usuarios de linux
##sys1='chmod go+r'
##sys2=paste(sys1, '', newfile)
##system(sys2)

## Esto devuelve un mensaje al terminar la función
print1='¡¡¡Ya está!!!, ¡¡¡mira que gráfico más chulo en'
print2=paste(print1, '', newfile, sep='')
print (print2);

$BODY$
LANGUAGE 'plr' VOLATILE
</pre>
<p>Dentro de la función hay que destacar el empleo de pg.spi.exec(),  para uso de los desarrolladores de PostgreSQL, que ejecuta una expresión dada.</p>
<p>Una vez creada nuestra función la podremos ejecutar de un modo muy sencillo. Fijaos que bueno que es esto  <img src='http://www.gisandchips.org/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />    :</p>
<pre class="brush: sql; title: ; notranslate">

select _plr_hist('un campo numérico', 'tabla');
</pre>
<p>Y obtenemos nuestra gráfica en la carpeta especificada.</p>
<h3>Algunos comentarios sobre todo esto:</h3>
<p>Viéndolo ya funcionar parece que nada “malo” pueda pasarnos. A este respecto, uno de los aspectos que más problemas me creó en su día es lo relacionado con los derechos del usuario Postgres en el SO, tanto en Linux como en Windows. La solución en linux viene dada y comentada en el código de más arriba. Con “chmod go+r” damos derechos de lectura a todos los usuarios. Lo que no me imaginaba nunca es que en Windows también iba a tener problemas. Resulta que el usuario que ejecuta el postmaster de Postgresql es “postgres”, que no dispone de derechos de escritura (no se si hay otros problemas) en “c:\”. Cuando se trata de crear una salida gráfica a c:\, el interprete de pl/R indica que no se puede iniciar el device(). Esto me llevó algún dolor de cabeza pues en Windows suelo hacer todas mis primeras pruebas directamente en c:\. En el ejemplo de antes trabajamos en un directorio creado a propósito. Sobre esto último podemos consultar en <a href="http://pgfoundry.org/pipermail/plr-general/2009-June/000264.html">http://pgfoundry.org/pipermail/plr-general/2009-June/000264.html</a> .</p>
<h3>Referencias:</h3>
<p>Solamente recordaros lo esencial de la página de Joe Conway (<a href="http://www.joeconway.com/plr/">http://www.joeconway.com/plr/</a> ). También os recomiendo entrar en <a href="http://www.bostongis.com/">http://www.bostongis.com/</a> donde hay un hilo de 3 artículos explicando distintos temas relacionados con pl/R. El primero es una introducción bastante detallada, el segundo es trata la creación de polígonos de Voronoi en PostgreSQL usando PostGIS y pl/R (muy recomendable, y avanzado), y el último es un ejemplo de uso de RGDAL.</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>Si quereis contactar podeis enviarme un email (asunto: gisandchips):</p>
<p>Benito M. Zaragozí</p>
<p>benito.zaragozi@ua.es</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gisandchips.org/2009/09/24/integracion-de-r-en-postgresql-mi-primera-funcion-en-plr/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

