<?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; Consejo práctico</title>
	<atom:link href="http://www.gisandchips.org/category/tip/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>Proyección segura desde UTM ED50 con interfaz gráfico</title>
		<link>http://www.gisandchips.org/2011/11/28/proyeccion-segura-desde-utm-ed50-con-interfaz-grafico/</link>
		<comments>http://www.gisandchips.org/2011/11/28/proyeccion-segura-desde-utm-ed50-con-interfaz-grafico/#comments</comments>
		<pubDate>Mon, 28 Nov 2011 19:52:39 +0000</pubDate>
		<dc:creator>jose</dc:creator>
				<category><![CDATA[Consejo práctico]]></category>
		<category><![CDATA[ed50]]></category>
		<category><![CDATA[epsg]]></category>
		<category><![CDATA[etrs89]]></category>
		<category><![CDATA[ogr2ogr]]></category>

		<guid isPermaLink="false">http://www.gisandchips.org/?p=1963</guid>
		<description><![CDATA[Seguramente muchos de vosotros habéis estado en la tesitura de tener que proyectar vuestras capas de datos gis que usan la vetusta y a extinguir proyección UTM con datum ED50. Lo de que dicha proyección &#8220;no esta de moda&#8221; no es algo causal, puesto que hay un Real Decreto, el 1071, que define como sistema [...]]]></description>
			<content:encoded><![CDATA[<p>Seguramente muchos de vosotros habéis estado en la tesitura de tener que proyectar vuestras capas de datos gis que usan la vetusta y a extinguir proyección UTM con datum ED50. Lo de que dicha proyección &#8220;no esta de moda&#8221; no es algo causal, puesto que hay un Real Decreto, el 1071, que define como sistema geodésico oficial de referencia para España aquel con el datum ETRS89 y el elipsoide SGR80. Bien es cierto que el decreto permite la ambivalencia de ambos sistemas (ETRS89 y ED50) hasta el año 2015; fecha a partir del cual diremos adiós definitivamente a ED50 (Elipsoide Hayford).<br />
Por otra parte, con el auge de los wikimaps es bastante habitual tener que realizar reproyecciones de las capas gis con ED50 &#8220;de toda la vida&#8221; al sistema geodésico mundial WGS84, que es lo que admiten casi todas las geowikis (OpenStreetMap, ikiMaps, geoNames, etc.).<br />
<div id="attachment_1989" class="wp-caption aligncenter" style="width: 496px"><p class="wp-caption-text">Reproyección mal realizada</p></div><a href="http://www.gisandchips.org/?attachment_id=1989"><img src="http://www.gisandchips.org/wp-content//ua_etrs89_mal.png" alt="Reproyección mal realizada" width="550" class="aligncenter size-full wp-image-1991" /></a><br />
<span id="more-1963"></span><br />
Pero, ¿que es lo que ocurre cuando utilizamos de forma genérica las utilidades de reproyección de los programas de GIS?. Casi todos, generan datos erróneos, que de ninguna manera se corresponden con la realidad. He encontrado translaciones en la X de más de 100 metros, y unos 50 en la Y respecto a la coordenada donde debería estar. </p>
<p>He probado diferentes métodos (sin transformación, transformación EPSG) y el resultado es muy dispar. Sólo un de los métodos funciona bien, aquel cuya transformación utiliza la rejilla en formato NTv2 del IGN, que fue creado precisamente para la transformación de datos desde ED50.<br />
<div id="attachment_1991" class="wp-caption aligncenter" style="width: 496px"><p class="wp-caption-text">Reproyección con rejilla del IGN</p></div><a href="http://www.gisandchips.org/?attachment_id=1991"><img src="http://www.gisandchips.org/wp-content//sigua_ed50.png" alt="Reproyección con rejilla IGN" width="500" class="alignnone size-full wp-image-1991" /></a><br />
Para este artículo he creído conveniente proponer un método de reprojección que no haga uso de ningún programa GIS, y que podamos lanzarlo cómodamente desde la consola (eso de &#8220;cómodamente&#8221; a alguno le sonará a coña). Lo que quería era simplemente un programa que le indicase mi dato en UTM ED50 y me lo proyecte a lo que quiera. Finalmente he decidido crear un híbrido que esté a medio camino entre el &#8220;terminal&#8221; Linux y un interfaz gráfico (en este caso &#8220;GTK&#8221;).<br />
Como no se trata de reinventar la rueda, he utilizado una herramienta con la que me siento muy cómodo y me ha sacado más de una vez de un apuro. Se trata de &#8220;ogr2ogr&#8221;, un comando que forma parte de la suite de GDAL. Este comando está diseñado para cambiar de formato nuestros datos, pero también para reproyectar. Si sintaxis está llena de modificadores que lo hacen a veces un poco críptico.<br />
Entrando en harina, sí deseamos reproyectar un fichero en ED50 a otra proyección la sintaxis es:</p>
<pre class="brush: bash; title: ; notranslate">ogr2ogr -s_srs &quot;EPSG:23030&quot; -t_srs epsg_destino destino origen</pre>
<p>Este comando tampoco solucionaría los problemas para ED50, por lo que habría que retocar el comando de esta forma para que utilice la rejilla del IGN:</p>
<pre class="brush: bash; title: ; notranslate">ogr2ogr -s_srs '+init=epsg:23030 +nadgrids=./peninsula.gsb +wktext' -t_srs epsg_destino origen destino</pre>
<p>Coincidiréis conmigo que este comando con todas sus opciones no es muy intuitivo para recordar. Por esta razón he decidido utilizar un interfaz gráfico para el terminal (sí, no habéis oído mal) que permite lanzar los típicos formularios gráficos para rellenar los datos. En definitiva, no se hace nada más que encapsular dicho comando con cuadros de diálogo que se lanzan al X-windows. Hay algunas utilidades para ello: Xdialog (x-windows), dialog (para el terminal), kdialog (para KDE). Yo voy a utilizar uno llamado &#8220;Zenity&#8221;, que está en todas las distribuciones linux.<br />
Finalmente he creado un script BASH que empotra las peticiones (selección del EPSG, de ficheros, alertas, comprobaciones, etc.) en diálogos hechos con Zenity.<br />
Este es el codigo:</p>
<pre class="brush: bash; title: ; notranslate">
#!/bin/sh
zenity --info --text=&quot;OGR2OGR Dialog \n
Autor: José Manuel Mira \n
GISandCHIPS 2011 \n
Aplicación basada en OGR2OGR para convertir \n
shapefile proyectado en UTM con datum ED50 en huso 30 (EPSG:23030) a  \n
Geodésica mundial con datum WGS84 (epsg:4326) o \n
UTM ETRS89 (epsg:25830) utilizando GDAL. \n
NOTA: Esta utilidad necesita la rejilla del IGN \n
descargable en: \n

http://www.gisandchips.org/demos/j3m/ogr/peninsula.gsb&quot;

# Comprobar que está instalado OGR2OGR
if which ogr2ogr &gt; /dev/null; then
echo &quot;GDAL está instalado&quot;
else
echo &quot;No está instalado GDAL&quot; | zenity --error --text=&quot;No está instalado GDAL. Salir \n ¿Ubuntu? sudo apt-get install gdal-bin&quot;
exit
fi
#Comprobamos que tienes la rejilla instalada en el directorio del script
if [ -f ./peninsula.gsb ]
then
  echo &quot;OK, tienes la rejilla&quot; | zenity --info --text=&quot;OK, tienes la rejilla&quot;
else
  echo &quot;Descargando rejilla ...&quot;
  wget http://www.gisandchips.org/demos/j3m/ogr/peninsula.gsb 2&gt;=1 | sed -u 's/.*\ \([0-9]\+%\)\ \+\([0-9.]\+\ [KMB\/s]\+\)$/\1\n# Downloading \2/' | zenity --progress --title=&quot;Descargando rejilla IGN ...&quot;
fi

origen=$(zenity --file-selection --title=&quot;Selecciona un shapefile en proyección ED50&quot;)
case $? in
  0)
    echo &quot;\&quot;$origen\&quot; selected.&quot;;;
  1)
    exit;;
   -1)
    exit;;
esac

# obtener extensión del fichero
ext=${origen#*.}
echo $ext
if [ $ext != 'shp' ]
then
   echo &quot;No es un shapefile. Salir&quot; | zenity --error --text=&quot;NO es un shapefile. Salir&quot;
   exit
fi

destino=$(zenity --entry --text &quot;Nombre del Shapefile de salida (sin .shp)?&quot; --entry-text &quot;destino&quot;); echo $destino
if [ $? = 1 ]
then
 exit
else
 echo $?
fi

epsg=$(zenity  --list  --text &quot;Selecciona la proyección de salida&quot; --radiolist  --column &quot;Sel&quot; --column &quot;EPSG&quot; --column &quot;Nombre&quot; TRUE 4326 &quot;Geodésica WGS84&quot; FALSE 25830 &quot;UTM ETS89 HUSO 30&quot;  FALSE 25831 &quot;UTM ETS89 HUSO 31&quot;  FALSE 25829 &quot;UTM ETS89 HUSO 29&quot;); 

echo &quot;ogr2ogr -s_srs '+init=epsg:23030 +nadgrids=./peninsula.gsb +wktext' -t_srs EPSG:&quot;${epsg} ${destino}-${epsg}.shp $origen
ogr2ogr -s_srs '+init=epsg:23030 +nadgrids=./peninsula.gsb +wktext' -t_srs EPSG:${epsg} ${destino}-${epsg}.shp $origen
zenity --info --text &quot;Shapefile ${destino}-${epsg}.shp creado satisfactoriamente&quot;
</pre>
<p>Guardamos el script como conversor.sh, le damos permisos de ejecución y lo lanzamos con </p>
<pre class="brush: bash; title: ; notranslate">sh ./conversor.sh</pre>
<p> Estos son algunos de los diálogos que aparecen:<br />
<img src="http://www.gisandchips.org/wp-content//dialogo_shapefile.png" alt="Indicar shapefile" /><br />
<img src="http://www.gisandchips.org/wp-content//dialogo_rejilla.png" alt="Descarga rejilla IGN" /><br />
<img src="http://www.gisandchips.org/wp-content//dialogo_ok.png" alt="Fin diálogo" /><br />
<img src="http://www.gisandchips.org/wp-content//dialogo_epsg.png" alt="Lista SRS" /><br />
Sí, ya se lo que estáis pensando (tanto rollo para una sola línea de comando). Es cierto, pero resulta útil y sencillo para aquellos que no se quieren complicar la vida. Además, con ligeras modificaciones lo puedo hacer extensible a las islas, otros husos, escribir un log con comandos para reutilizarlos en el futuro en modo BATCH, etc)<br />
He realizado algunas pruebas para comprobar la validez de los datos reproyectados utilizando coordenadas de vértices geodésicos y visualizadas sobre un fondo con el WMS del PNOA. El resultado salta a la vista: &#8220;lo ha cuadrado&#8221;<br />
<div id="attachment_1990" class="wp-caption aligncenter" style="width: 496px"><p class="wp-caption-text">Comparación original (EPSG:23030) y proyectada a WGS84 (EPSG:4326)</p></div><a href="http://www.gisandchips.org/?attachment_id=1990"><img src="http://www.gisandchips.org/wp-content//comparacion_23030-4326.png" alt="comparación 23030-4326" width="570" class="alignnone size-full wp-image-1990" /></a></p>
<p>Sí deseas probar el script <a href="/demos/j3m/ogr/vgeo.zip" title="Descarga vértices geodésicos">aquí</a> tienes unas shapes de prueba (vértices geodésicos en 23030) de la Comunidad Valenciana)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gisandchips.org/2011/11/28/proyeccion-segura-desde-utm-ed50-con-interfaz-grafico/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Business card de GISchips (en LaTeX)</title>
		<link>http://www.gisandchips.org/2011/11/06/business-card-de-gischips-en-latex-3/</link>
		<comments>http://www.gisandchips.org/2011/11/06/business-card-de-gischips-en-latex-3/#comments</comments>
		<pubDate>Sun, 06 Nov 2011 18:41:06 +0000</pubDate>
		<dc:creator>benizar</dc:creator>
				<category><![CDATA[Consejo práctico]]></category>
		<category><![CDATA[Business card]]></category>
		<category><![CDATA[GIS & Chips]]></category>
		<category><![CDATA[LaTeX]]></category>
		<category><![CDATA[OpenStreetMap]]></category>

		<guid isPermaLink="false">http://www.gisandchips.org/?p=1847</guid>
		<description><![CDATA[La semana pasada estaba previsto que varios miembros de GIS&#38;Chips presentáramos un taller en una Jornada de Geografía 3.0. Además, algunos asistimos al posterior congreso nacional de geografía. Finalmente, no se pudo realizar el taller por falta de horarios, pero esperamos poder organizar algún evento propio solamente para la difusión de conocimientos de TIG libre. [...]]]></description>
			<content:encoded><![CDATA[<p>La semana pasada estaba previsto que varios miembros de GIS&amp;Chips presentáramos un taller en una Jornada de Geografía 3.0. Además, algunos asistimos al posterior congreso nacional de geografía. Finalmente, no se pudo realizar el taller por falta de horarios, pero esperamos poder organizar algún evento propio solamente para la difusión de conocimientos de TIG libre.</p>
<p>En estos eventos es habitual el intercambio de tarjetas de presentación y como no teníamos una para darnos a conocer decidimos hacer una prueba en LaTeX, que no salió del todo mal. En este post compartimos esta primera versión para que la podáis personalizar o simplemente ver como se ha hecho.</p>
<div id="attachment_1825" class="wp-caption aligncenter" style="width: 315px"><img class="size-full wp-image-1825" src="http://www.gisandchips.org/wp-content//GC_businessCard_front1.jpg" alt="" width="305" height="152" /><p class="wp-caption-text">Cara tarjeta G&amp;C, generado con el fichero &quot;G&amp;C_businessCard_front.tex&quot;.</p></div>
<p style="text-align: center">
<p><span id="more-1847"></span></p>
<h3>Características a considerar en el diseño</h3>
<p>Hace mucho tiempo di un par de cursos para el diseño de marca. Ilustrator, Freehand y Photoshop para el diseño de tarjetas, trípticos, carteles, carátulas de cds, etc. Hay que reconocer que todo esto es una profesión en sí y hay muchos detalles por conocer. En tal caso, lo que hacemos nosotros aquí es un “apaño”, por lo que nadie espere grandes cosas <img src='http://www.gisandchips.org/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Las características más a tener en cuenta en el diseño son el tamaño de la tarjeta, el logo, el fondo y la gama de colores. Otra cuestión a tener en cuenta es la problemática vector-raster.</p>
<p>El <strong>tamaño</strong> de la tarjeta se puede determinar por una serie de estándares, supongo que según el tamaño de los billetes de cada país <img src='http://www.gisandchips.org/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  (la cartera donde guardamos las tarjetas también depende de esto). Nuestra tarjeta (90x45mm) no se ajusta a ninguno de estos estándares aunque la podríamos adaptar muy fácilmente. En <a title="http://en.wikipedia.org/wiki/Business_card" href="http://en.wikipedia.org/wiki/Business_card" target="_blank">http://en.wikipedia.org/wiki/Business_card</a> encontramos los tamaños más utilizados.</p>
<p>El <strong>logo</strong> es el  que figura en el blog, diseñado por Miguel. No obstante, eliminamos el texto pues lo incluiremos entre los otros elementos de la tarjeta.</p>
<p>El <strong>fondo de la cara frontal</strong> es una nube de tags basada en la de esta página, después en Gimp le hemos añadido un degradado lineal de negro a blanco. El<strong> fondo del reverso</strong> es un mapa de <a href="http://www.openstreetmap.org/">http://www.openstreetmap.org/</a> que indica la ubicación de la sede. Para completar la ubicación se podría añadir la dirección en texto.</p>
<p>El nombre de la asociación, el lema y los datos de contacto (web y Email) aparecen en la cara frontal. El contraste blanco/negro es uno de los más recurridos y elegantes aunque esto dependerá del gusto de cada uno, además son los colores que aparecen en el blog.</p>
<p>Finalmente, la problemática raster-vector hace que no todos los programas sean igual de prácticos al combinar imágenes con texto en un marco tan pequeño. El texto podría verse mal al rasterizarse en Gimp o las imágenes verse mal por no estar bien escaladas al tamaño del papel. Para evitar problemas es recomendable preparar todos los componentes del diseño en un marco de 90x45mm. Además, conviene que el texto sea siempre vectorial.</p>
<div id="attachment_1828" class="wp-caption aligncenter" style="width: 341px"><img class="size-full wp-image-1828 " src="http://www.gisandchips.org/wp-content//GC_businessCard_back.jpg" alt="" width="331" height="165" /><p class="wp-caption-text">Reverso de la tarjeta G&amp;C, generado con el fichero &quot;G&amp;C_businessCard_back.tex&quot;.</p></div>
<h3>¿Porqué LaTeX?</h3>
<p>Seguramente, podríamos haber creado la tarjeta solamente con Gimp, Impress, Inkscape o cualquier otro software comercial… incluso en un editor de textos cualquiera. O con una máquina de escribir… No obstante, para crear la tarjeta hemos utilizado Gimp y LaTeX.</p>
<p>Básicamente, prefiero esta opción porqué es FOSS y estándar. No necesitamos conocer demasiados botones y LaTeX lleva una larga trayectoria de más de 20 años que hace pensar que la plantilla que creemos seguirá siendo funcional en el futuro. Además, ya utilizo LaTeX para hacer pósters, artículos, presentaciones, materiales docentes, el currículum y mi tesis. De este modo, la pregunta sería ¿porqué aprender otros programas?</p>
<p>Desgraciadamente, no puedo aquí hacer un tutorial de LaTeX para geógrafos pero, si necesitáis escribir un documento estructurado de grandes dimensiones (tesis) o muchos de otro tipo (informes) os animo a que le echéis un vistazo a este proyecto tan interesante pues a medio plazo os ahorrará muchos dolores de cabeza.</p>
<h3>Como está hecha</h3>
<p>Las plantillas que he encontrado en la web (buscando “Business card; LaTeX”) son más bien sosas con un estilo próximo al de la máquina de escribir y además son bastante complejas. Para evitar estos problemas hemos utilizado la clase “Beamer” de LaTeX, que permite entre otras cosas añadir una imagen de fondo y formatear el espacio de la tarjeta apropiadamente.</p>
<p>Primero, hemos utilizado Gimp para crear los fondos de la tarjeta como dos ficheros PNG. A continuación, LaTeX se ha utilizado para la composición, añadir textos y dibujos vectoriales (líneas). En el reverso de la tarjeta hemos añadido un mapa de <a href="http://www.openstreetmap.org/">http://www.openstreetmap.org/</a> para aportar una localización más detallada, aunque también se podría añadir la dirección postal.</p>
<p>La plantilla se compone de tres ficheros TeX, uno para cada cara de la tarjeta y, tras compilar las dos caras, el tercero para crear una composición de 12 tarjetas a dos caras.</p>
<p><img class="size-full wp-image-1830 alignnone" src="http://www.gisandchips.org/wp-content//GC_businessCard_x12_Página_1.jpg" alt="" width="214" height="303" /><img class="alignnone size-full wp-image-1831" src="http://www.gisandchips.org/wp-content//GC_businessCard_x12_Página_2.jpg" alt="" width="214" height="303" /></p>
<p>Esta plantilla es altamente mejorable, es una versión 0.1 para salir del paso, pero os puede dar ideas. La idea de aprovechar OSM para la localización (idea de José) es interesante y evita tener que pensar en hacer un croquis como he visto en algunas tarjetas. Además, creo que los detalles de la tarjeta (la nube de tags como fondo, el mapa…) además de quedar bastante bien aportan información extra sobre nosotros si se saben leer.</p>
<h3>Código en latex</h3>
<p>Finalmente, os paso el código de los tres ficheros de LaTeX necesarios para crear esta tarjeta. Si leéis el código veréis donde podéis introducir vuestras propias imágenes de fondo o el logo que queráis. Espero que os sea de ayuda y os genere otras ideas.</p>
<p><strong>G&#038;C_businessCard_front.tex</strong></p>
<p>
<pre class="brush: latex; title: ; notranslate">
% GIS&amp;Chips nice business card
% By Benito M. Zaragozí
% Version 0.1 released 02/11/2011
% Further releases in: www.gisandchips.org
% This template is composed by three .tex files (businessCard.tex, businessCard_back.tex and businessCardx10.tex) for preparing a basic layout.

\documentclass{beamer}
\usepackage[utf8x]{inputenc}
\usepackage[spanish]{babel}
\usepackage{hyperref}
\usepackage[absolute,showboxes,verbose,overlay]{textpos}
\usepackage{geometry}
\geometry{paperwidth=90mm, paperheight=45mm, layoutwidth=90mm, layoutheight=45mm, left=0mm, top=0mm, right=0mm, bottom=0mm}

\usetheme{default}

\setbeamertemplate{navigation symbols}{}
\setbeamertemplate{background canvas}{\includegraphics[height=\paperheight]{background.png}}

\begin{document}

\frame{
\begin{columns}
	\begin{column}{35mm}
		\includegraphics[width=44mm]{gischips_logo.png}
	\end{column}

	\begin{column}{40mm}
		\color{white}{Asociación\\ \vspace{1mm} \huge{GIS \&amp;amp; Chips}}
		\normalsize
		\vspace{1mm}
		\line(1,0){80}
		\vspace{-1mm}
		\color{white}{Geografía útil para llevar}
	\end{column}
\end{columns}

\vspace{-1mm}
\normalsize
\color{black}{\hspace{5mm}\line(1,0){220}\\ \hspace{2mm} \url{www.gisandchips.org} \hspace{3mm} \url{info@gisandchips.org}}
}
\end{document}
</pre>
</p>
<p><strong>G&#038;C_businessCard_back.tex</strong></p>
<p><strong></strong>
<pre class="brush: latex; title: ; notranslate">
% GIS&amp;Chips nice business card
% By Benito M. Zaragozí
% Version 0.1 released 02/11/2011
% Further releases in: www.gisandchips.org
% This template is composed by three .tex files (businessCard.tex, businessCard_back.tex and businessCardx10.tex) for preparing a basic layout.

\documentclass{beamer}
\usepackage[utf8x]{inputenc}
\usepackage[spanish]{babel}
\usepackage{geometry}
\geometry{margin=2mm, paperwidth=90mm, paperheight=45mm}

\usetheme{default}
\setbeamertemplate{navigation symbols}{}
\setbeamertemplate{background canvas}{\hspace{2mm} \includegraphics[height=41.5mm]{mapbackground.png}}

\begin{document}
	\frame{
		\vspace{-1.5mm}
		\colorbox{white}{GIS\&amp;amp;Chips en la Universidad de Alicante}\\
		\vspace{31mm}
		\begin{flushright}
		\colorbox{white}{\tiny {\url{www.openstreetmap.org}}}
		\end{flushright}
	}
\end{document}
</pre>
</p>
<p><strong>G&#038;C_businessCard_x12.tex</strong></p>
<p><strong></strong>
<pre class="brush: latex; title: ; notranslate">
% GIS&amp;Chips nice business card
% By Benito M. Zaragozí
% Version 0.1 released 02/11/2011
% Further releases in: www.gisandchips.org
% This template is composed by three .tex files (businessCard.tex, businessCard_back.tex and businessCardx10.tex) for preparing a basic layout.

\documentclass[10pt,a4paper]{minimal}
\usepackage{graphicx}
\usepackage[margin=1cm]{geometry}

\begin{document}
\thispagestyle{empty}
\noindent

\begin{center}
\hspace{1mm}\includegraphics[scale=1]{businessCard.pdf} \includegraphics[scale=1]{businessCard.pdf} \vspace{1mm}

\hspace{1mm}\includegraphics[scale=1]{businessCard.pdf} \includegraphics[scale=1]{businessCard.pdf} \vspace{1mm}

\hspace{1mm}\includegraphics[scale=1]{businessCard.pdf} \includegraphics[scale=1]{businessCard.pdf} \vspace{1mm}

\hspace{1mm}\includegraphics[scale=1]{businessCard.pdf} \includegraphics[scale=1]{businessCard.pdf} \vspace{1mm}

\hspace{1mm}\includegraphics[scale=1]{businessCard.pdf} \includegraphics[scale=1]{businessCard.pdf} \vspace{1mm}

\hspace{1mm}\includegraphics[scale=1]{businessCard.pdf} \includegraphics[scale=1]{businessCard.pdf} \vspace{1mm}

\pagebreak
%%%%%%Back with map
\hspace{1mm}\includegraphics[scale=1]{businessCard_back.pdf} \includegraphics[scale=1]{businessCard_back.pdf} \vspace{1mm}

\hspace{1mm}\includegraphics[scale=1]{businessCard_back.pdf} \includegraphics[scale=1]{businessCard_back.pdf} \vspace{1mm}

\hspace{1mm}\includegraphics[scale=1]{businessCard_back.pdf} \includegraphics[scale=1]{businessCard_back.pdf} \vspace{1mm}

\hspace{1mm}\includegraphics[scale=1]{businessCard_back.pdf} \includegraphics[scale=1]{businessCard_back.pdf} \vspace{1mm}

\hspace{1mm}\includegraphics[scale=1]{businessCard_back.pdf} \includegraphics[scale=1]{businessCard_back.pdf} \vspace{1mm}

\hspace{1mm}\includegraphics[scale=1]{businessCard_back.pdf} \includegraphics[scale=1]{businessCard_back.pdf} \vspace{1mm}

\end{center}
\pagebreak
\end{document}
</pre></p>
]]></content:encoded>
			<wfw:commentRss>http://www.gisandchips.org/2011/11/06/business-card-de-gischips-en-latex-3/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>Edición de geometrías en NTS con CoordinateArrayFilter</title>
		<link>http://www.gisandchips.org/2009/11/04/edicion-de-geometrias-en-nts-con-coordinatearrayfilter/</link>
		<comments>http://www.gisandchips.org/2009/11/04/edicion-de-geometrias-en-nts-con-coordinatearrayfilter/#comments</comments>
		<pubDate>Wed, 04 Nov 2009 11:09:09 +0000</pubDate>
		<dc:creator>josetomas</dc:creator>
				<category><![CDATA[Consejo práctico]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[CoordinateArrayFilter]]></category>
		<category><![CDATA[JTS]]></category>
		<category><![CDATA[NTS]]></category>

		<guid isPermaLink="false">http://www.gisandchips.org/?p=747</guid>
		<description><![CDATA[Java Topology Suite (JTS) es una librería que resuelve problemas complejos y en la que sus arquitectos han recurrido al uso exhaustivo de patrones de diseño de software como medio de gestionar eficientemente dicha complejidad. Como muestra baste mencionar que los desarrolladores debemos asumir desde el principio el factory pattern que implementa la clase GeometryFactory [...]]]></description>
			<content:encoded><![CDATA[<p><a title="Java Topology Suite" href="http://www.vividsolutions.com/jts/JTSHome.htm" target="_blank">Java Topology Suite</a> (JTS) es una librería que resuelve problemas complejos y en la que sus arquitectos han recurrido al uso exhaustivo de <a title="patrones de diseño de software" href="http://en.wikipedia.org/wiki/Design_pattern_(computer_science)" target="_blank">patrones de diseño de software</a> como medio de gestionar eficientemente dicha complejidad. Como muestra baste mencionar que los desarrolladores debemos asumir desde el principio el <a title="factory pattern" href="http://en.wikipedia.org/wiki/Factory_pattern" target="_blank"><em>factory pattern</em></a> que implementa la clase <em>GeometryFactory</em> que empleamos en la construcción de objetos geométricos. El hecho de que JTS haga uso de patrones de diseño es una muestra más de su fiabilidad, aunque en ocasiones (sobretodo si hay carencia de documentación) también implica un esfuerzo extra por nuestra parte a la hora de entender cómo se solucionan determinados casos de uso. Uno de esos casos en los que la solución no se evidencia a primera vista es la edición de los vértices de una geometría, así que en este  artículo os muestro código de ejemplo para el porting de JTS a C#, <a title="NetTopologySuite" href="http://code.google.com/p/nettopologysuite/" target="_blank">NetTopologySuite</a> (NTS) en su versión 1.2, que os permitirá introduciros en el manejo del interface <em>ICoordinateFilter </em>para la manipulación geométrica.<span id="more-747"></span></p>
<p>Quizá me equivoque, pero creo que no se puede calificar JTS/NTS como un &#8220;framework&#8221; para el desarrollo de herramientas de  manipulación de geometrías (e.g. aplicaciones tipo CAD). El diseño de este API promueve más bien la idea de inmutabilidad de un objeto geométrico a lo largo de su ciclo de vida (aunque no hay un mecanimo que fuerze dicha inmutabilidad), y se centra en la modelización a bajo nivel de las tareas de cálculo topológico y análisis espacial, y en la exactitud de los resultados derivados de un geoproceso, todo ello en función de las recomendaciones del <a title="OGC Simple Feature Access specification" href="http://www.opengeospatial.org/standards/sfa" target="_blank">Open Geospatial Consortium</a>.</p>
<p>Pero es probable que, en algún punto de una secuencia de geoprocesamiento, necesitemos manipular las coordenadas de una geometría (por ejemplo, forzar una corrección de forma transparente para el  usuario). Asumiendo que el array de coordenadas almacena la secuencia de vértices actual en lugar de una copia (que la propiedad <em>Coordinates </em>sea o no una copia depende de la secuencia de coordenadas empleada en la construcción de la geometría; tenéis más información sobre esto en el capítulo 8 de la <a title="JTS Developer's Guide" href="http://www.vividsolutions.com/jts/bin/JTS%20Developer%20Guide.pdf" target="_blank">guía del desarrollador de JTS</a>), nada nos impide editar diréctamente los valores en ese array. También podríamos copiar dicho array, operar sobre los vértices en cuestión, instanciar una nueva geometría y desechar la antigua. Discutir sobre la idoneidad de estas soluciones no es objeto de este artículo. Lo que interesa es que sepamos que el propio API proporciona otras vías específicas para la edición de vértices.</p>
<p>En concreto, si tan sólo necesitamos operar con las coordenadas existentes (no añadir ni borrar), NTS proporciona el interfaz <em>ICoordinateFilter</em>, a partir del cual pueden derivarse clases que implementen el <a title="visitor pattern" href="http://en.wikipedia.org/wiki/Visitor_pattern"><em>visitor pattern</em></a> para operar con la lista de coordenadas de cualquier tipo de geometría. Cada desarrollador puede implementar sus propias operaciones o filtros de coordenadas a conveniencia, pero NTS ya proporciona unos cuantos: <em>UniqueCoordinateArrayFilter</em>, <em>CoordinateCountFilter </em>y, el más simple y objeto de nuestro interés,  <em>CoordinateArrayFilter</em>, que da acceso al array completo de coordenadas para su manipulación.</p>
<h2>Veamos un ejemplo</h2>
<p>Suponed que tenemos el siguiente LineString:</p>
<pre>LINESTRING (100 100,  150 180,  200 210,
            210 140,  100 110,  100 100)</pre>
<p>Si lo visualizárais en vuestro cliente favorito observaríais algo similar a esto:</p>
<p style="padding-left: 90px"><img class="size-medium wp-image-632" src="http://www.gisandchips.org/wp-content/CoordinateArrayFilter1-300x222.png" alt="LineString con autointersección" width="300" height="222" /></p>
<p>Esta geometría presenta una autointersección que NTS permite detectar de diversas formas. Nosotros nos centraremos en corregirla aplicando un criterio muy simple: intercambiaremos los valores de las coordenadas en las posiciones 0 y 4. Aquí tenéis el código fuente de esta operación de desplazamiento de vértices:</p>
<pre class="brush: csharp; title: ; notranslate">
using System;
using GisSharpBlog.NetTopologySuite.Geometries;
using GisSharpBlog.NetTopologySuite.IO;
using GisSharpBlog.NetTopologySuite.Utilities;

namespace CoordFilter
{
 class Program
 {
  public static void Main(string[] args)
  {
   string wkt = &quot;LINESTRING (100 100,  150 180,  200 210, 210 140,  100 110,  100 100)&quot;;
   WKTReader r = new WKTReader();
   Geometry g = r.Read(wkt);
   //Creamos sendas copias de las coordenadas objeto de desplazamiento
   Coordinate c0 = new Coordinate(g.Coordinates[0]);
   Coordinate c4 = new Coordinate(g.Coordinates[4]);
   //Instanciamos el filtro; puesto que queremos acceso a todo el array
   //de coordenadas de nuestra geometría, indicamos el tamaño del array
   CoordinateArrayFilter filter = new CoordinateArrayFilter(g.NumPoints);
   //El método Apply vuelca el array de coordenadas de la geometría en
   //el array de coordenadas del filtro
   g.Apply(filter);
   //Realizamos la operación de desplazamiento de vértices
   //sobre el array de coordenadas del filtro
   filter.Coordinates[0].X = c4.X;
   filter.Coordinates[0].Y = c4.Y;
   filter.Coordinates[4].X = c0.X;
   filter.Coordinates[4].Y = c0.Y;
   filter.Coordinates[5].X = c4.X;
   filter.Coordinates[5].Y = c4.Y;
   //Notificamos la actualización para que el Envelope pueda recalcularse
   g.GeometryChanged();
   Console.WriteLine(g.ToText());
   Console.Write(&quot;Press any key to continue . . . &quot;);
   Console.ReadKey(true);
  }
 }
}
</pre>
<p>Si ejecutáis el código, obtendréis el siguiente resultado en WKT:</p>
<pre>LINESTRING (100 110,  150 180,  200 210,
            210 140,  100 100,  100 110)</pre>
<p>Y este sería el resultado gráfico:</p>
<p style="padding-left: 90px"><img class="size-medium wp-image-657" src="http://www.gisandchips.org/wp-content/CoordinateArrayFilter2-300x221.png" alt="LineString modificado con CoordinateArrayFilter" width="300" height="221" /></p>
<h2>¿Qué hay del modelo de precisión?</h2>
<p>Lo cierto es que la clase CoordinateArrayFilter no toma en consideración el modelo de precisión de la geometría a modificar. Entonces ¿cómo podemos controlar que, ante un desplazamiento, las coordenadas se calculen sobre el &#8220;grid&#8221; de referencia asociado a la geometría? Una opción es utilizar la clase <em>GeometryEditor</em>, lo que implica generar una nueva geometría a partir de la antigua. Pero ya que hablamos de filtros y traslado de coordenadas, ¿por qué no derivar una clase de tipo ICoordinateFilter que, dado un desplazamiento (dx, dy), mueva una geometría al completo respetando su modelo de precisión? Aquí tenéis un ejemplo:</p>
<pre class="brush: csharp; title: ; notranslate">
using System;
using GisSharpBlog.NetTopologySuite.Geometries;
using GisSharpBlog.NetTopologySuite.IO;

namespace CoordFilter
{
 class Program
 {
  public static void Main(string[] args)
  {
   string wkt = &quot;LINESTRING (100.24 100.5, 150.82 180.56, 200.06 210.1, 210.44 140.82, 100.24 100.5)&quot;;
   //Asumiendo que la unidad principal es el metro, asociamos un &quot;grid&quot; centimétrico
   //a nuestro objeto GeometryFactory.
   WKTReader r = new WKTReader(new GeometryFactory(new PrecisionModel(100)));
   Geometry g = r.Read(wkt);
   //Instanciamos el filtro; puesto que queremos acceso a todo el array
   //de coordenadas de la geometría a desplazar, indicamos el tamaño del array;
   //además indicamos el modelo de precisión de dicha geometría.
   GeometryMoveFilter filter = new GeometryMoveFilter(g.NumPoints, g.Factory.PrecisionModel);
   g.Apply(filter);
   filter.Move(5.342237891, 3.865754133);
   g.GeometryChanged();
   Console.WriteLine(g.ToText());
   Console.Write(&quot;Press any key to continue . . . &quot;);
   Console.ReadKey(true);
  }

  //Clase derivada de ICoordinateFilter para el desplazamiento
  //de geometrías acorde con un modelo de precisión. El código de esta
  //clase está basado en el de la clase CoordinateArrayFilter de NTS,
  //cuyo autor es Diego Guidi.
  class GeometryMoveFilter : ICoordinateFilter
  {
   Coordinate[] pts = null;
   int n = 0;
   PrecisionModel grid = null;

   //Al igual que la clase CoordinateArrayFilter, el constructor necesita
   //el tamaño del array de coordenadas. Adicionalmente se necesita el
   //objeto PrecisionModel que define el &quot;grid&quot; de referencia
   public GeometryMoveFilter(int size, PrecisionModel model)
   {
    pts = new Coordinate[size];
    grid = model;
   }

   //Este método aplica un desplazamiento en X y en Y sobre
   //cada coordenada
   public void Move(double xOffset, double yOffset)
   {
    for(int i = 0; i &lt; n; i++)
    {
     Coordinate c = pts[i];
     //Aplicamos el desplazamiento
     c.X += xOffset;
     c.Y += yOffset;
     //Ajustamos la coordenada al &quot;grid&quot; de referencia
     grid.MakePrecise(ref c);
    }
   }

   public void Filter(Coordinate coord)
   {
    pts[n++] = coord;
   }
  }
 }
}
</pre>
<p>Si lo ejecutáis deberíais obtener el siguiente resultado:</p>
<p>LINESTRING (105.58 104.37, 156.16 184.43, 205.4 213.97, 215.78 144.69, 105.58 104.37)</p>
<p>Recordad que si estáis trabajando con NTS 1.2 hay que solucionar previamente un &#8220;bug&#8221; que afecta a la clase <em>PrecisionModel</em>. En <a title="modelos de precisión fija en NTS" href="http://www.gisandchips.org/2009/11/03/como-definir-y-usar-modelos-de-precision-fija-en-nts/" target="_blank">este artículo</a> encontraréis información sobre cómo resolverlo.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gisandchips.org/2009/11/04/edicion-de-geometrias-en-nts-con-coordinatearrayfilter/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cómo definir y usar modelos de precisión fija en NTS</title>
		<link>http://www.gisandchips.org/2009/11/03/como-definir-y-usar-modelos-de-precision-fija-en-nts/</link>
		<comments>http://www.gisandchips.org/2009/11/03/como-definir-y-usar-modelos-de-precision-fija-en-nts/#comments</comments>
		<pubDate>Tue, 03 Nov 2009 13:14:29 +0000</pubDate>
		<dc:creator>josetomas</dc:creator>
				<category><![CDATA[Consejo práctico]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[fixed PrecisionModel]]></category>
		<category><![CDATA[JTS]]></category>
		<category><![CDATA[MakePrecise]]></category>
		<category><![CDATA[NTS]]></category>

		<guid isPermaLink="false">http://www.gisandchips.org/?p=470</guid>
		<description><![CDATA[En JTS Topology Suite el modelo de precisión  es un mecanismo central que determina la robustez de los cálculos geométricos y topológicos. En las especificaciones técnicas de este API libre para el análisis espacial encontrareis una detallada exposición de las implicaciones del modelo de precisión, principalmente en lo que se refiere a situaciones de colapso [...]]]></description>
			<content:encoded><![CDATA[<p>En <a title="JTS Topology Suite" href="http://www.vividsolutions.com/JTS/JTSHome.htm" target="_blank">JTS Topology Suite</a> el modelo de precisión  es un mecanismo central que determina la robustez de los cálculos geométricos y topológicos. En las <a title="especificaciones técnicas" href="http://www.vividsolutions.com/jts/bin/JTS%20Technical%20Specs.pdf" target="_blank">especificaciones técnicas</a> de este API libre para el análisis espacial encontrareis una detallada exposición de las implicaciones del modelo de precisión, principalmente en lo que se refiere a situaciones de colapso dimensional. Por ejemplo, podemos encontrarnos una situación de colapso dimensional cuando a partir de una geometría topológicamente válida calculada sobre un modelo de doble precisión (i.e. un polígono calculado mediante un objeto <em>Polygonizer</em>) obtenemos su representación en WKT y al intentar renderizarlo en una aplicación externa obtenemos un error de validación topológica (i.e. el polígono contiene una autointersección).</p>
<p>Cuando nos vemos en esta coyuntura, es decir, en la necesidad de transferir geometría entre aplicaciones mediante un formato interoperable pero de precisión limitada (i.e. DXF, WKT), hay que plantearse el uso de un modelo de precisión fija, a saber, un modelo que nos permita definir un &#8220;grid&#8221; al que siempre estarán referidas nuestras coordenadas, tanto las de origen como las derivadas del cálculo. En este breve artículo tenéis ejemplos de código fuente que os orientarán sobre cómo aplicar la clase <em>PrecisionModel</em> para trabajar con un &#8220;grid&#8221; de referencia en <a title="NetTopologySuite" href="http://code.google.com/p/nettopologysuite/" target="_blank">NetTopologySuite</a> (NTS), el porting de JTS a C#, en su versión 1.2.<span id="more-470"></span></p>
<p>Definir un &#8220;grid&#8221; es sencillo. Basta con crear una instancia de la clase <em>PrecisionModel</em> y asignarlo al objeto <em>GeometryFactory</em> mediante el cual construyamos nuestras geometrías. Cada geometría así instanciada heredará una referencia a un &#8220;grid&#8221; que determinará cualquier cálculo en el que dicha geometría intervenga posteriormente. Pero, ¿cómo se especifica la precisión de dicho  &#8220;grid&#8221;? Asignando un <strong>factor de escala</strong> que equivale al denominador de la fracción deseada de la unidad principal. Por ejemplo, si la unidad principal es el metro asignaremos 100 para trabajar en centímetros (coordenadas con un máximo de 2 decimales), 1000 para trabajar en milímetros (coordenadas con un máximo de 3 decimales), 200 para trabajar con una precisión de 0.5 centímetros, &#8230;</p>
<pre class="brush: cpp; title: ; notranslate">
using System;
using GisSharpBlog.NetTopologySuite.Geometries;

namespace Grids
{
 class Program
 {
  public static void Main(string[] args)
  {
   //Definición de varios &quot;grids&quot; asumiendo que trabajamos en metros
   PrecisionModel mGrid = new PrecisionModel(PrecisionModels.Fixed); //precisión métrica
   PrecisionModel mGrid2 = new PrecisionModel(1); //equivale al anterior
   PrecisionModel cmGrid = new PrecisionModel(100); //precisión centimétrica
   PrecisionModel mmGrid = new PrecisionModel(1000); //precisión milimétrica
   PrecisionModel halfcmGrid = new PrecisionModel(200); //0.5 cm de precisión
  }
 }
}
</pre>
<p>Cuando se parte de geometrías expresadas como <a title="WKT" href="http://en.wikipedia.org/wiki/Well-known_text" target="_blank">WKT</a>, la aplicación del &#8220;grid&#8221; a la imagen en memoria de las nuevas geometrías es transparente para el programador. Basta con asignar al objeto <em>WKTReader</em> el correspondiente objeto <em>GeometryFactory</em>. Esto significa que si probáis este código:</p>
<pre class="brush: cpp; title: ; notranslate">
using System;
using GisSharpBlog.NetTopologySuite.Geometries;
using GisSharpBlog.NetTopologySuite.IO;

namespace Grids
{
 class Program
 {
  public static void Main(string[] args)
  {
   string wkt = &quot;POLYGON ((253722.078898558 4292685.50730101, 253722.07889856 4292685.50730102, 253735.282733042 4292698.56531273, 253738.905778592 4292696.94218745, 253741.840165249 4292695.62758151, 253735.276565443 4292675.86615228, 253717.38 4292636.98, 253700.54 4292646.23, 253722.078898558 4292685.50730101))&quot;;
   PrecisionModel grid = new PrecisionModel(1000); //precisión milimétrica
   GeometryFactory gf = new GeometryFactory(grid); //vinculamos el &quot;grid&quot; con un objeto GeometryFactory
   WKTReader r = new WKTReader(gf); //asociamos el objeto GeometryFactory con el intérprete de WKT
   Console.WriteLine(r.Read(wkt).ToText()); //de WKT a Geometry y de nuevo a WKT
   Console.Write(&quot;Press any key to continue . . . &quot;);
   Console.ReadKey(true);
  }
 }
}
</pre>
<p>Éste es el resultado que deberíais obtener:</p>
<pre>POLYGON ((253722.079 4292685.507, 253722.079 4292685.507,
          253735.283 4292698.565, 253738.906 4292696.942,
          253741.84 4292695.628, 253735.277 4292675.866,
          253717.38 4292636.98, 253700.54 4292646.23,
          253722.079 4292685.507))</pre>
<p>Sin embargo, puede ocurrir que nuestros datos de entrada se presenten como lista de pares (x,y). En este caso, el programador es responsable de hacer que cada coordenada se ajuste previamente a la precisión del &#8220;grid&#8221; de referencia. Esto se consigue de manera efectiva invocando al método <em>MakePrecise</em> del correspondiente objeto <em>PrecisionModel</em>. El siguiente ejemplo ilustra una solución para el polígono del ejemplo anterior, dada su lista de coordenadas.</p>
<pre class="brush: cpp; title: ; notranslate">
using System;
using GisSharpBlog.NetTopologySuite.Geometries;
using GisSharpBlog.NetTopologySuite.IO;

namespace Grids
{
 class Program
 {
  public static void Main(string[] args)
  {
   List&lt;double[]&gt; coords = new List&lt;double[]&gt;();
   coords.Add(new double[]{253722.078898558, 4292685.50730101});
   coords.Add(new double[]{253722.07889856, 4292685.50730102});
   coords.Add(new double[]{253735.282733042, 4292698.56531273});
   coords.Add(new double[]{253738.905778592, 4292696.94218745});
   coords.Add(new double[]{253741.840165249, 4292695.62758151});
   coords.Add(new double[]{253735.276565443, 4292675.86615228});
   coords.Add(new double[]{253717.38, 4292636.98});
   coords.Add(new double[]{253700.54, 4292646.23});
   coords.Add(new double[]{253722.078898558, 4292685.50730101});

   PrecisionModel grid = new PrecisionModel(1000); //precisión milimétrica
   GeometryFactory gf = new GeometryFactory(grid); //vinculamos el &quot;grid&quot; con un objeto GeometryFactory
   Geometry g = GetPolygon(coords, gf); //instanciamos el polígono a partir de la lista de coordenadas y el objeto GeometryFactory
   Console.WriteLine(g.ToText()); //mostramos el resultado en WKT
   Console.Write(&quot;Press any key to continue . . . &quot;);
   Console.ReadKey(true);
  }

  static Polygon GetPolygon(List&lt;double[]&gt; coords, GeometryFactory gf)
  {
   List&lt;Coordinate&gt; fixedCoords = new List&lt;Coordinate&gt;();
   foreach (double[] xyPair in coords)
   {
    fixedCoords.Add(GetFixedCoordinate(xyPair[0], xyPair[1], gf));
   }
   return gf.CreatePolygon(gf.CreateLinearRing(fixedCoords.ToArray()), null);
  }

  static Coordinate GetFixedCoordinate(double x, double y, GeometryFactory gf)
  {
   Coordinate c = new Coordinate(x, y);
   gf.PrecisionModel.MakePrecise(ref c); //cálculo de coordenada precisa, es decir, referida al &quot;grid&quot; del modelo de precisión milimétrica que lleva aparejado el objeto GeometryFactory
   return c;
  }
 }
}
</pre>
<p>Si ejecutáis este código deberíais obtener un resultado idéntico al anterior.</p>
<h2>¿Y si no funciona &#8230;?</h2>
<p>Como  dije al principio, podéis usar NTS 1.2 para probar estos ejemplos. Si preferís usar NTS 1.7 seguramente necesitaréis efectuar pequeños cambios en el código. De todos modos, tanto con la versión 1.2 como con la 1.7.1 hay un &#8220;bug&#8221; que hace que, independientemente del factor de escala, el modelo de precisión  fija quede referido siempre a la unidad principal, es decir, a coordenadas enteras. Este &#8220;bug&#8221; está corregido en la versión 1.7.3. Lo bueno de trabajar con software libre es que en la mayoría de casos (y éste es uno de ellos) la solución está a nuestro alcance. Así que, los que trabajéis con la versión 1.2, podéis descargar el código fuente <a title="NTS 1.2 download" href="http://sourceforge.net/projects/nts/files/NetTopologySuite/NetTopologySuite%201.2%20Final%20Release/NetTopologySuite_20feb06.zip/download">aquí</a> y modificar la línea <strong>351</strong> del fichero <strong>PrecisionModel.cs</strong>. Donde dice:</p>
<pre>return Math.Floor(((val * scale) + 0.5d) / scale);</pre>
<p>simplemente debe decir:</p>
<pre>return Math.Floor((val * scale) + 0.5d) / scale;</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.gisandchips.org/2009/11/03/como-definir-y-usar-modelos-de-precision-fija-en-nts/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

