<?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; PostGIS</title>
	<atom:link href="http://www.gisandchips.org/tag/postgis/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>Creación de un mapfile de forma dinámica (&#8220;al vuelo&#8221;)</title>
		<link>http://www.gisandchips.org/2009/11/02/creacion-de-un-mapfile-de-forma-dinamica-al-vuelo/</link>
		<comments>http://www.gisandchips.org/2009/11/02/creacion-de-un-mapfile-de-forma-dinamica-al-vuelo/#comments</comments>
		<pubDate>Mon, 02 Nov 2009 10:47:11 +0000</pubDate>
		<dc:creator>pepe</dc:creator>
				<category><![CDATA[Programación]]></category>
		<category><![CDATA[mapfile]]></category>
		<category><![CDATA[mapscript]]></category>
		<category><![CDATA[mapserver]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[PostGIS]]></category>
		<category><![CDATA[programación]]></category>

		<guid isPermaLink="false">http://www.gisandchips.org/?p=383</guid>
		<description><![CDATA[Este artículo va encaminado a la publicación de cartografía en Internet de forma dinámica, utilizando PHPMapScript. Lo que vamos a intentar conseguir es mostrar en una página web un fichero de mapa sin la necesidad de tener un fichero .map (MapFile) asociado y complejo de mantener, simplemente realizando modificaciones en nuestro código php. Este es [...]]]></description>
			<content:encoded><![CDATA[<p>Este artículo va encaminado a la publicación de cartografía en Internet de forma dinámica, utilizando PHPMapScript.</p>
<p>Lo que vamos a intentar conseguir es mostrar en una página web un fichero de mapa sin la necesidad de tener un fichero .map (MapFile) asociado y complejo de mantener, simplemente realizando modificaciones en nuestro código php.</p>
<p>Este es el resultado que queremos obtener:</p>
<div id="attachment_1085" class="wp-caption aligncenter" style="width: 310px"><img class="size-medium wp-image-1085" title="4b025a29_5fd1_1" src="http://www.gisandchips.org/wp-content/4b025a29_5fd1_1-300x300.gif" alt="Mapa de españa" width="300" height="300" /><p class="wp-caption-text">Mapa de españa</p></div>
<p style="text-align: center">
<p>Vamos a ponernos manos a la obra para conseguirlo.</p>
<p>En primer lugar, doy por supuesto que tenemos instalado MapServer y MapScript en nuestro servidor Linux (en mi caso CentOS)  y el Servidor de Bases de Datos PostgreSQL+PostGIS y con la extensión PHP/pgSQL.</p>
<p>Creamos un fichero .php</p>
<p>Lo primero que debemos hacer es cargar la librería PHPMapScript (<em>php_mapscript.so</em>)</p>
<p><span id="more-383"></span></p>
<pre class="brush: php; title: ; notranslate">

dl('php_mapscript.so');

//Una vez cargada la librería ya se puede trabajar con las funciones propias de PHPMapScript
//Para empezar hay que crear el fichero mapa y definir las diferentes características que queremos que tenga el mapa (nombre, tamaño,

//Creamos un objeto llamado Map mediante el Constructor de MapObject

$Map=ms_newMapObj(&quot;&quot;);

//Le damos un nombre (p.e. mapa)
$Map-&gt;set(&quot;name&quot;,&quot;Mapa&quot;);

//La dimensión del mapa
$Map-&gt;setSize(600,600);

// La extensión del mapa (la podemos obtener de postgresql mediante la función de postgis st_extent
$Map-&gt;setExtent(626679.9375,4191059,815673.125,4519371);

// Se define el path de la imagen la temporal y la real que se mostrarán por web
$Map-&gt;web-&gt;set(&quot;imagepath&quot;,&quot;/tmp&quot;);
$Map-&gt;web-&gt;set(&quot;imageurl&quot;,&quot;/ms_tmp&quot;);

Una vez hemos definido las características de nuestro fichero de mapa, procedemos a incluir capas.
&lt;pre&gt;//Definimos una capa asociada a nuestro fichero de mapa anteriormente definido
// En este caso la primera capa, y que va a servir de fondo de nuestro mapa va a ser wms
// y del servicio wms que proporciona el &lt;a href=&quot;http://www.idee.es/wms/PNOA/PNOA?Request=GetCapabilities&amp;Service=WMS&quot; target=&quot;_blank&quot;&gt;PNOA&lt;/a&gt;&lt;/pre&gt;
$Layer1=ms_newLayerObj($Map);

$Layer1-&gt;set(&quot;name&quot;,&quot;ortofoto&quot;);

//Tipo Raster

$Layer1-&gt;set(&quot;type&quot;,MS_LAYER_RASTER);

$Layer1-&gt;set(&quot;status&quot;,MS_ON);//El status de la Layer, esto nos permitirá definir layers y mantenerlas ocultas dependiendo de las necesidades que tengamos
$Layer1-&gt;setConnectionType(MS_WMS);
$Layer1-&gt;set(&quot;connection&quot;,&quot;http://www.idee.es/wms/PNOA/PNOA?&quot;);
//Definimos la proyección del wms junto con el nombre de la capa wms, la versión del servidor y el formato de la imagen
&lt;pre&gt;//El que esta capa se muestre o no, no depende de nosotros, depende de una fuente externa que proporciona la capa WMS, en este caso es la del PNOA&lt;/pre&gt;
$Layer1-&gt;setProjection(&quot;init=epsg:23030&quot;);
$Layer1-&gt;setMetadata(&quot;wms_name&quot;,&quot;pnoa&quot;);
$Layer1-&gt;setMetadata(&quot;wms_server_version&quot;,&quot;1.1.1&quot;);
$Layer1-&gt;setMetadata(&quot;wms_format&quot;,&quot;image/png&quot;);

//Como segunda capa asociada a nuestro fichero de mapa anteriormente definido vamos a añadir una capa obtenida de nuestros datos en postgresql
$Layer2=ms_newLayerObj($Map);

//Vamos definiendo las características que va a tener esta nuestra primera capa
$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
$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
// MUY IMPORTANTE es necesario incluir el unique gid y using srid=23030, si no no funcionará
$Layer2-&gt;set(&quot;data&quot;,&quot;geometria from ine.municipios using unique gid using srid=23030&quot; );
//Una vez definida la estructura d ela capa procedemos a definir el estilo de nuestra capa número 1

$clase = ms_newClassObj($Layer2); //Definimos la clase
$estilo = ms_newStyleObj($clase); //El estilo asociado a dicha clase
$estilo-&gt;color-&gt;setRGB(10,150,190); //Los colores
$estilo-&gt;outlinecolor-&gt;setRGB(0,0,0); //El contorno

//Una vez hemos definido las capas tenemos que indicar que se dibuje el mapa
$Image=$Map-&gt;Draw();

//Muy importante que no se nos olviden estas 2 sentencias que vienen a continuación, si no ponemos que se almacene la imagen en el path que le hemos incluido o no la mostramos por pantalla con un echo, no va a mostarse nada, y caeremos en el desanimo ya que después de definir todo correctamente la página aparece en blanco.

$url_imagen=$Image-&gt;saveWebImage();
echo &quot;&lt;img src=&quot;.$url_imagen.&quot;&gt;&quot;;
</pre>
<p>Y después de tener esto, solo hay que lanzar el navegador y et voilà!, tenemos nuestro primer mapfile utilizando PHPMapScript en nuestro navegador, puede que sea un poco lento a la hora de cargar, pero no depende tanto de nuestra capa en PostGIS sino del Servidor WMS que utilicemos como capa de fondo, que ya no depende de nosotros.</p>
<p>El resultado es este: <a href="http://www.gisandchips.org/demos/mapscript/index.php" target="_blank">http://www.gisandchips.org/demos/mapscript/index.php</a></p>
<p style="text-align: center;">
]]></content:encoded>
			<wfw:commentRss>http://www.gisandchips.org/2009/11/02/creacion-de-un-mapfile-de-forma-dinamica-al-vuelo/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Simplify Workbench: banco de pruebas para geometría simplificada</title>
		<link>http://www.gisandchips.org/2009/04/29/simplify-workbench-banco-de-pruebas-para-geometria-simplificada/</link>
		<comments>http://www.gisandchips.org/2009/04/29/simplify-workbench-banco-de-pruebas-para-geometria-simplificada/#comments</comments>
		<pubDate>Wed, 29 Apr 2009 09:40:18 +0000</pubDate>
		<dc:creator>josetomas</dc:creator>
				<category><![CDATA[Programación]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[geometry simplification]]></category>
		<category><![CDATA[PostGIS]]></category>
		<category><![CDATA[SharpMap]]></category>

		<guid isPermaLink="false">http://www.gisandchips.org/wordpress/?p=22</guid>
		<description><![CDATA[Optimizar nuestro cliente GIS, tanto para web como para escritorio, implica entre otras cosas afinar al máximo los rangos de escala de visualización para cada una de nuestras capas. Sin embargo puede darse el caso de que este mecanismo no sea aplicable. Ante esta situación, es importante que no renunciemos al ahorro en los tiempos [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify">Optimizar nuestro cliente GIS, tanto para web como para escritorio, implica entre otras cosas afinar al máximo los rangos de escala de visualización para cada una de nuestras capas. Sin embargo puede darse el caso de que este mecanismo no sea aplicable. Ante esta situación, es importante que no renunciemos al ahorro en los tiempos de proceso, y en este sentido puede ser útil recurrir a la simplificación o generalización de la geometría.</p>
<p style="text-align: justify">Lo que aquí os ofrecemos es una herramienta que, dada una determinada entidad PostgreSQL/PostGIS, permite explorar rápidamente cuál es la relación entre tamaño de imagen, extensión del mapa, degradación visual y tiempo de proceso <span id="more-22"></span>para un máximo de 4 valores de tolerancia designados por el usuario. Se trata de una aplicación sencilla, escrita en C#, en la que el área de trabajo se divide en cuatro paneles. En cada panel podemos asignar una tolerancia, visualizar la geometría simplificada resultante, echar un vistazo a la sentencia SQL ejecutada en PostgreSQL y comprobar el tiempo de proceso transcurrido en realizar la transacción en el servidor y generar la imagen resultante en el cliente. Además, en todo momento conocemos cuál es la dimensión en píxeles de la imagen y el ancho del mapa. La instantánea inferior muestra una sesión de Simplify Workbench en la que se compara la geometría simplificada de los municipios de España procedentes de la Base de Datos de Líneas Límite a escala 1:1.000.000 del <a title="IDEE" href="http://www.idee.es" target="_blank">IDEE</a>. Se puede observar cómo el tiempo de proceso del panel C es casi 4 veces menor que el del panel A, mientras que el impacto en la visualización es casi inapreciable. Por el contrario, la reducción del tiempo de proceso en el panel D conlleva una degradación visual que, para la resolución de la imagen, no es aceptable.</p>
<div id="attachment_42" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.gisandchips.org/wp-content/simplifyworkbench3.png"><img class="size-medium wp-image-42" src="http://www.gisandchips.org/wp-content/simplifyworkbench3-300x290.png" alt="Geometría simplificada de los municipios de España en Simplify Workbench. Fuente de datos: IDEE" width="300" height="290" /></a><p class="wp-caption-text">Geometría simplificada de los municipios de España en Simplify Workbench. Fuente de datos: IDEE</p></div>
<p style="text-align: center">
<p style="text-align: justify">Podéis disponer del código fuente de Simplify Workbench bajo licencia GPL haciendo un <em>checkout </em>del siguiente repositorio Subversion de GIS&amp;Chips:</p>
<p style="text-align: justify;padding-left: 30px"><code>svn co http://www.gisandchips.org/svn/simplifyworkbench</code></p>
<p style="text-align: justify">Para los que queráis probarlo de inmediato, tened en cuenta que los datos de conexión a PostgreSQL y entidad PostGIS se configuran en el fichero XML <strong>app.config</strong> que acompaña al ejecutable. Por defecto, os proporcionamos una conexión al servidor PostgreSQL de GIS &amp; Chips para que podáis hacer tests con los municipios del IDEE. Si vais a realizar pruebas con vuestros propios datos tened en cuenta que la función de simplificación de PostGIS (<em>simplify</em> o <em>st_simplify</em>) no opera sobre geometrías en coordenadas geográficas (e.g. SRID = 4326), por lo que la aplicación no realizará el tratamiento esperado. Tampoco opera sobre entidades con sistema de referencia espacial indeterminado en la tabla <em>geometry_columns </em>(i.e. SRID = -1).</p>
<p style="text-align: justify">Si eres desarrollador y te vas a &#8216;zambullir&#8217; en el código seguramente te interesará conocer que Simplify Workbench no es más que una extensión de <a title="SharpMap" href="http://www.codeplex.com/SharpMap" target="_blank">SharpMap</a> con un interfaz gráfico en Windows.Forms. Formalmente es una solución desarrollada en el IDE de código abierto <a title="SharpDevelop" href="http://www.icsharpcode.net/OpenSource/SD/" target="_blank">SharpDevelop</a>, escrita en C# sobre el framework 2.0 de .NET. Integra tres proyectos:  <strong>SharpMap </strong>(versión 0.9), <strong>SharpMapSimplifyExtension</strong> y <strong>Simplify</strong>.</p>
<p style="text-align: justify">Seguramente alguno de vosotros ya conozca <a title="SharpMap" href="http://www.codeplex.com/SharpMap" target="_blank">SharpMap</a>. Desde que <a title="Morten Nielsen" href="http://www.sharpgis.net/" target="_blank">Morten Nielsen</a>, su creador, publicó allá por 2005-2006  este versátil renderizador de cartografía basado en GDI+, una pequeña revolución se ha producido en el ámbito de los clientes GIS libres sobre plataforma .NET y de hecho el proyecto no sólo continúa muy activo sino que ha conseguido integrar un equipo consolidado de desarrolladores en torno a un ecosistema de proyectos interrelacionados. El proyecto <strong>SharpMap</strong> de Simplify Workbench corresponde a los fuentes de la versión 0.9, la versión estable, aunque observaréis que el namespace SharpMap.Data.Providers incluye el proveedor de PostGIS (<a title="PostGIS.cs" href="http://sharpmap.codeplex.com/Wiki/View.aspx?title=PostGIS" target="_blank">PostGIS.cs</a>) y una referencia a <a title="Npgsql" href="http://npgsql.projects.postgresql.org/" target="_blank">Npgsql</a>, la librería de acceso a datos de PostgreSQL en su versión 2.0.4.</p>
<p style="text-align: justify">El proyecto <strong>SharpMapSimplifyExtension</strong> consta de dos clases: <strong>PostGISSimplify</strong> y <strong>VectorSimplifiedLayer</strong>. La primera es una derivación de la clase SharpMap.Data.Providers.PostGIS que modifica el método <em>GetGeometriesInView</em> de forma que la sentencia SQL subyacente invoque la función <em>simplify</em> de PostGIS con la tolerancia de entrada. También añade un delegado que permite recuperar mediante un evento tanto la sentencia SQL final como el ancho del <em>bounding box</em>. La segunda deriva de la clase SharpMap.Layers.VectorLayer, sobrecarga el constructor para instanciar capas vectoriales especificando una tolerancia de simplificación y modifica el método <em>Render</em>. Con estas dos simples extensiones podemos definir  una capa vectorial que muestre geometría simplificada de PostGIS sin variar sustancialmente la lógica habitual de trabajo con SharpMap, tal y como se muestra en este ejemplo:</p>
<pre class="brush: csharp; title: ; notranslate">
//
//
//
string cnstr = &quot;Server=your.pgsql.server;Port=5432;User Id=user;Password=secret;Database=yourDB&quot;;
string tableName = &quot;yourPolygons&quot;;
string geomFieldName = &quot;geometry&quot;;
string oidFieldName = &quot;oid&quot;;
//Instance of data provider for PostGIS simplified geometry
PostGISSimplify src = new PostGISSimplify(cnstr, tableName, geomFieldName, oidFieldName);
//Instance of vector layer to hold simplified PostGIS geometry
//Third parameter is an integer corresponding to tolerance in Douglas-Peucker vertex reduction algorithm
VectorSimplifiedLayer lyr = new VectorSimplifiedLayer(&quot;SIMPLIFIED_LAYER&quot;, src, 1000);
lyr.Style.EnableOutline = true;
lyr.Style.Fill = Brushes.Transparent;
//Map object, the layer container and rendering logic construct in SharpMap
Map m = new Map(new System.Drawing.Size(350, 275));
m.BackColor = Color.White;
m.Layers.Add(lyr);
//Zoom to extents internally invokes the modified GetGeometriesInView method in PostGISSimplify class
m.ZoomToExtents();
//Retrieve map image
System.Drawing.Image img = m.GetMap();
//
</pre>
<p style="text-align: justify">El proyecto <strong>Simplify</strong> incluye el formulario estructurado en cuatro paneles comentado más arriba y una clase de conveniencia, <strong>MapRenderer</strong>, que encapsula la lógica de lectura del fichero app.config, definición de layer, obtención de la imagen, recuperación de la sentencia SQL y cálculo del tiempo de proceso. En el directorio de este proyecto encontraréis también el fichero de solución de SharpDevelop (Simplify.sln).</p>
<p style="text-align: justify">Para terminar, y puesto que muchos de nosotros aquí en GIS &amp; Chips somos fans del framework de código abierto Mono, os animamos a que probéis a compilar usando esta plataforma. Sabemos positivamente que SharpMap 0.9, con pequeñas modificaciones, es compilable sobre Mono. Creemos, aunque no lo hemos comprobado, que el código de Simplify Workbench también lo es. Si alguno lo consigue nos alegrará que nos lo comente.</p>
<p style="text-align: justify">¡Disfrutad con Simplify Workbench!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gisandchips.org/2009/04/29/simplify-workbench-banco-de-pruebas-para-geometria-simplificada/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

