<?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; JTS</title>
	<atom:link href="http://www.gisandchips.org/tag/jts/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>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>

