tag:blogger.com,1999:blog-47514585479390653692024-02-07T14:33:01.847-08:00Oscar Fernandez AsuncionOscar Enrique Fernández Asunción, Ingeniero Informático, Universidad Nacional de Trujillohttp://www.blogger.com/profile/07877105547794172771noreply@blogger.comBlogger6125tag:blogger.com,1999:blog-4751458547939065369.post-22686095325865710672009-04-13T18:03:00.000-07:002009-04-13T19:34:59.198-07:00DETECCION DE BORDES: algoritmo de Canny<div align="justify">El operador de detección de bordes de Canny fue desarrollado por un catedrático de la universidad de Berkeley (EEUU) en 1986 y se basa en un algoritmo de múltiples fases para detectar un amplio rango de bordes. Es sin duda el operador más utilizado en la detección de bordes<br />El objetivo de Canny era descubrir el algoritmo óptimo para la detección de bordes. Un detector óptimo significará una buena detección, el algoritmo debe marcar tantos bordes reales como sea posible, una buena localización, los bordes marcados deben estar lo más cerca posible del borde en la imagen real, y por último una mínima respuesta, es decir, un borde dado debe ser marcado sólo una vez y donde sea posible el ruido presente en la imagen no debería crear falsos bordes.<br /><br /></div><div align="justify"><div align="justify"></div><ol><li><div align="justify"><strong>Operador de Canny:</strong><br />Esta técnica, que se caracteriza por estar optimizada para la detección de bordes diferenciales, consta de 3 fases pero algunos autores agregan una ultima fase, siendo en total 4 fases.<br /><br /></div></li><li><div align="justify"><strong>Fases de detección de bordes de canny:</strong><br />-Obtención del gradiente<br />-Supresión no máxima al resultado del gradiente<br />-Histéresis de umbral a la supresión no máxima<br />-Cierre de contornos abiertos<br /><strong>Obtención del gradiente: </div><img id="BLOGGER_PHOTO_ID_5324351201431400098" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 287px; CURSOR: hand; HEIGHT: 64px; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMYbxNJJm5DwKy6pyWc-tvXFdBp1sQjUfSNvu82XQUO6-bU3NZrYnCUGn0JYvqNqX_91yxgAVh032Go4xa_6pzxprH3HgOQo2Xcn6B-SHOEQVmATXhvynhquMS0D5QKQBOj72xTrnqD2Td/s400/Dibujo3.bmp" border="0" /><br />·</strong> Para obtener el gradiente se tiene que suavizar la imagen<br />-Aplicar a la imagen I un suavizado gaussiano G o filtro gaussiano (también se puede aplicar otros filtros ) J = I * G<br />- Para calcular el kernel gaussiano G utilizar la siguiente ecuación<img id="BLOGGER_PHOTO_ID_5324349174479790834" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 188px; CURSOR: hand; HEIGHT: 52px; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgavqa2JAieItwqgtKSAcR7dNZpO9WWgC_C-i42Q7AQ-9hujAk6y7CVgshZoiSUqUfPnZQHDn_uMn-PdPPS5Qvw-COoyTNwj3YwwV47PhPbnQ2lelUItVv4Ndh8tqcZ0okx0PM-GwLh16RK/s400/Dibujo.bmp" border="0" /> · En seguida calcular el gradiente:<br />- Para cada pixel de la imagen J(i,j)<br />->Calcular las componentes del gradiente Jx y Jy<br />->Calcular la magnitud de los bordes <img id="BLOGGER_PHOTO_ID_5324349888381246162" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 224px; CURSOR: hand; HEIGHT: 35px; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBl80X9oTv3Yu3nyjfDJIvXHr67Iu1ky2SW6WSlieqETTLJgntPaW15xncbEj6gN2OW5lf4_t48P4NI8Klw4_L_SAT0XX3Q2uSz18yHlRAoIHtGauW_FPZZYG8-E2up7JP_nfG_bRtuUmk/s400/Dibujo1.bmp" border="0" /><br />->Estimar la orientación de la normal de los bordes<img id="BLOGGER_PHOTO_ID_5324350604319029570" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 147px; CURSOR: hand; HEIGHT: 46px; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_YX_xSCe22zWImMTkHfhNUzBb3gjmRR2xmSxLdxhXkbyCwopOfeSmHGGLCqfNsarBI5FtUStxBAOfrnO9fFn4FF89mTZs0a34wsjLYTlfLeXywRBTxeOu-U7rixCTXSSVsARJqYLe4wjb/s400/Dibujo2.bmp" border="0" /> <strong>Supresión no máxima al resultado del gradiente<br /></strong>El objetivo de este paso es Obtener bordes de 1 pixel de grosor al considerar únicamente pixels cuya magnitud es máxima en bordes gruesos y descartar aquellos cuyas magnitudes no alcancen ese máximo.<br />a) Para todo punto se obtiene la dirección más cercana dk a 0º, 45º,90º y 135º en Ea(i,j)<br />b) Si Em(i,j) es menor que uno de sus dos vecinos en la dirección dk,IN(i,j)=0. Si no IN(i,j)=Em(i,j)<br /><strong>Histéresis de umbral a la supresión no máxima<br /></strong>Permite eliminar máximos procedentes de ruido, etc.<br />-Entrada IN, Ea, y dos umbrales T1 y T2 (T2>T1)<br />-Para todo punto en IN, y explorando en un orden:<br />->Localizar el siguiente punto tal que IN(i,j) > T2<br />->Seguir las cadenas de máximos locales a partir de IN(i,j) en ambas direcciones perpendiculares a la normal al borde siempre que IN>T1. Marcar los puntos explorados.<br />-La salida es un conjunto de bordes conectados de contornos de la imagen, así como la magnitud y orientación.<br /><strong>Cierre de contornos abiertos </strong>(Algoritmo de Deriche y Cocquerez)<br />a) La imagen de entrada es una imagen de contornos binarizada (1= borde; 0=no borde)<br />b) Para cada punto de borde de un extremo abierto se le asigna un código que determina las direcciones de búsqueda para el cierre del contorno<br /><img id="BLOGGER_PHOTO_ID_5324354661848787874" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 387px; CURSOR: hand; HEIGHT: 69px; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcHB1QqINhGW8h47l10wXhhfBAUClpl4KVeHPb-ccCTFBwfwefa3OWGQcsG3zBjEz4VEjAKto5hBQ-KEziAfWZKALpsmYSRQ_eYPV-DJVww4zev0WCbrgnY32SqS8m-ktKbSkQ-OTNdQlo/s400/Dibujo4.bmp" border="0" />c) Para los pixels marcados con este código se marca como pixel de borde el de máximo gradiente en las tres direcciones posibles.<br />d) Se repiten los pasos hasta que se cierren todos los contornos.</li><br /><br /><li><div align="justify"><strong>Resultados:<img id="BLOGGER_PHOTO_ID_5324364185674164226" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 342px; CURSOR: hand; HEIGHT: 400px; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhB5jmDNXIgmU1Lb1VEWW31hxyAjsvHqukI11SIEWqpHu-iF96rM_h2JS9no7QyhUekEJ7A3PJKSAfDnc5ZVbs73RXfBjREWyQXu2hszFRlGVhBebsgbOGBFCRwK7OwQtEHRwNV4mDPD7Qy/s400/Dibujo7.bmp" border="0" /></strong></div></li><img id="BLOGGER_PHOTO_ID_5324365451220948114" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 341px; CURSOR: hand; HEIGHT: 525px; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSqUOxnGN-wQ2YVob5l8un-H9lVdX_6cwWawJphfLHR_3vCH3-S_9uzs1sxCqtN7v98eu_HxQbZ7k6P6StNFQImsqI6H_Ln4dpl4YVtGf5gGN2FNba8Y6vIQB1qrPgFC-juCca_lH6h4Gp/s400/Dibujo9.bmp" border="0" /> <li><div align="justify"><strong>Conclusiones:<br /></strong>a) Este algoritmo está considerado como uno de los mejores métodos de detección de contornos mediante el empleo de máscaras de convolución.<br /><br />b) El algoritmo Canny es adaptable a los varios ambientes. Sus parámetros permiten que sea adaptado al reconocimiento de los bordes de características que diferencian dependiendo de los requisitos particulares de una puesta en práctica dada.</div></li><br /><li><div align="justify"><strong>Ejecutable:<br /><br /></strong>Se implemento en matlab y en el programa se podra selecionar diferentes imagenes de prueba pero bien se puden poner otras imagenes con los mismos nombres. <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwf6Ac0uHMS6FZhWdyOabT8DaZasRZj_Wr3L6tglBvGZUJsxkf83sxgZsLh5uf8AES62f-KD5nUSSVZgEb7NoZ59TdsHqEdTQtOK4e05bWIUqWXZ8nsGC7OOFGvwTBJbgHgsNvI46MHqvb/s1600-h/Dibujo5.bmp"><img id="BLOGGER_PHOTO_ID_5324361892718032834" style="FLOAT: left; MARGIN: 0px 10px 10px 0px; WIDTH: 374px; CURSOR: hand; HEIGHT: 265px" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwf6Ac0uHMS6FZhWdyOabT8DaZasRZj_Wr3L6tglBvGZUJsxkf83sxgZsLh5uf8AES62f-KD5nUSSVZgEb7NoZ59TdsHqEdTQtOK4e05bWIUqWXZ8nsGC7OOFGvwTBJbgHgsNvI46MHqvb/s400/Dibujo5.bmp" border="0" /></a>Para ejecutar el programa primero se debe tener instalado el matlab 7.4 si no se tiene intalado ninguna version o otras versiones anteriores se debe instalar el componente (descargar las las 4 partes)<br /><a href="http://cid-3d37909d7ae99902.skydrive.live.com/self.aspx/blogger-oefa/MCRInstaller.part1.rar">Descargar Componente parte1</a><br /><a href="http://cid-3d37909d7ae99902.skydrive.live.com/self.aspx/blogger-oefa/MCRInstaller.part2.rar">Descargar Componente parte2</a><br /><a href="http://cid-3d37909d7ae99902.skydrive.live.com/self.aspx/blogger-oefa/MCRInstaller.part3.rar">Descargar Componente parte3</a><br /><a href="http://cid-3d37909d7ae99902.skydrive.live.com/self.aspx/blogger-oefa/MCRInstaller.part4.rar">Descargar Componente parte4</a><br /><br /><a href="http://cid-3d37909d7ae99902.skydrive.live.com/self.aspx/blogger-oefa/EjecutableCanny-FernandezAsuncionOscar.rar">Descargar Algortimo de Canny</a><br /></div></li></ol></div>Oscar Enrique Fernández Asunción, Ingeniero Informático, Universidad Nacional de Trujillohttp://www.blogger.com/profile/07877105547794172771noreply@blogger.com4tag:blogger.com,1999:blog-4751458547939065369.post-40204910384117180502008-11-11T12:56:00.000-08:002008-11-11T15:31:52.282-08:00Recuperación de Imágenes por Contenido Utilizando una Estructura de Datos Espacial Métrica<div align="justify">En el curso de Tópicos en Computación I realizamos un proyecto final con mis compañeros Murrugarra Llerena, Olivo Fukumoto y Linares Mestanza en este proyecto deberíamos aplicar alguna de las estructura de Datos Espacial desarrolladas en Laboratorio y fue de esa manera que realizamos este proyecto.</div><ol><li><div align="justify"><strong>INTRODUCCION<br /></strong>Nos ha pasado que cuando queremos buscar una imagen en Google tenemos que ingresar el nombre de la imagen (Ejemplo: gato) y los resultados son imágenes con el mismo nombre o con parte del nombre que ingresamos pero en muchos casos la imagen que nos devuelve no tiene nada que ver con la imagen que quisimos buscar esto sucede por que en la base de datos multimedia de imágenes sus elementos están indexados por sus nombres (sus clave son sus nombre). Ante este problema existe la recuperación de imágenes por contenido (28 de Abril del 2008 científicos de Google han sido capaces de desarrollar un algoritmo similar al PageRank pero que trabaja con el contenido de las imágenes y pronto podrán utilizar este tipo de tecnología).<br />En nuestro caso utilizaremos una Estructura de Datos Espacial Métrica M-tree para almacenar las imágenes de acuerdo una distancia entre ellas que se obtendrá aplicando un filtro de Gabor y calculando su vector característico para así poder hallar sus distancias.<img id="BLOGGER_PHOTO_ID_5267544995848042562" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 247px; CURSOR: hand; HEIGHT: 185px; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguiwcPlrBstoylu-XKMmtG5kk-WMB_ZQ77DkE6PxDZL1ZZsKvRPvBhRfwCHgwX31rAHepizjqgOizE1JZkMGDn3e3xSyjoVWnrjR3OL_rb2-jAnyWgi0w-Ju0a8-uf3eEcCyzlcFyQth3A/s400/Dibujo6.bmp" border="0" /></div></li><br /><br /><li><div align="justify"><strong>TRABAJOS PREVIOS<br /></strong>Entre los trabajos previos podemos encontrar:<br />Recuperación por contenido en bases de datos de imágenes basada en wavelets, Aplicación al Diseño del Textil, Manuel Agustí i Melchor Universidad Politécnica de Valencia: este trabajo estaba planteado para empresas más tradicionales de los sectores textil y cerámico que habían venido acumulando a lo largo de décadas un inmenso patrimonio compuesto por miles de muestras de telas y azulejos, deseaban tener a su disposición una base de datos multimedia para la recuperación según la textura que ellos requerían.<br />También podemos encontrar Recuperación de Imágenes Médicas por Contenido Usando Indexamiento medico, Edwin A Niño, Universidad Nacional de Colombia: en este trabajo se necesitaba tener una gran cantidad de imágenes medicas guardadas para después poder comparar o buscar imágenes parecidas que sean de utilidad para los medico y tener así una idea mas experimentada según las enfermedades y tumores ya almacenados en la base de datos multimedia de imágenes medicas. Otro antecedente importante fue Bases de datos para Multimedia, Recuperación por Contenido, José Miguel Valiente González, Universidad Politécnica de Valencia España: ente trabajo solo se centro en el como poder recuperar imágenes por contenido.<br /><br /></div></li><li><div align="justify"><strong>PASOS PARA LA RECUPERACION DE IMAGENES POR CONTENIDO</strong><br />Para iniciar la recuperación de imágenes por contenido seguimos los siguientes pasos:<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEscKtmWOG_3ODFavQ0W0rrGH1fq6Ku0K4BuyLI-I5qaN5KzIgGxb-0HlNaUu1x1r1t7PVC5gEh_KKMjEo2Gq-2AUC7e8CfoD5J2fcdyvrMXYf1nvpHzAaMpZqwjwfULTzeMhsDirzy6kp/s1600-h/Dibujo2.bmp"></a><br />· <strong>Construir M-tree con dos archivos: </strong>Archivo Registro (Informacion del objeto) y Archivo Indice (Nodos del M-tree).<br />·<strong> Aplicar filtro de Gabor</strong><br />· <strong>Calcular Vector Característico </strong></div></li></ol><img id="BLOGGER_PHOTO_ID_5267535958402149394" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 400px; CURSOR: hand; HEIGHT: 339px; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7Rt1S0QbEFEoA7gkhnMtsZIiLR0Huhq-VqylO775jwEVdu2TuMI6aJ9UuyjDzTTKqQeOITV8RSML7ra5DbCDTXFUzAddO9XrkNotyIm9RQeAxv-MpsoydTE2fJwuGOwRrHXoAh8Np34MI/s400/Dibujo2.bmp" border="0" /><br /><p align="justify"></p><ol><li><div align="justify"><strong>EXPERIMENTOS Y RESULTADOS</strong><br />Para la prueba de esta implementación se utilizaron 170 imágenes el tamaño de cada imagen fue de 200 * 200 se tomo en el filtro de Gabor orientaciones=5, escala=5, Ul = 0.1 (frecuencia espacial baja), Uh = 0.4 (frecuencia espacial alta), el T máximo en cada nodo del Mtree fue igual a 4, la distancia que se utilizo fue la distancia euclidiana.</div></li></ol><br /><p><img id="BLOGGER_PHOTO_ID_5267537427239476898" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 400px; CURSOR: hand; HEIGHT: 312px; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9TA8hT2dLqM-WyQw2nhTB8woyy8x9XiTiv60Unpk0dQzVpQ4AtqLKX_WT6c9CZqQx4zLOu_r4UZHmS0VfxrXO6bt-2bmLDxyoKxYoXPcW7wGEdq1h8sIUInZaQCHspg2FGRYXNc1Ll_Xo/s400/Dibujo3.bmp" border="0" /> </p><br /><p></p><img id="BLOGGER_PHOTO_ID_5267542420995512082" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 395px; CURSOR: hand; HEIGHT: 305px; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGZSBeNg9lsFGm8dnlCL9iG914zcg-aqMW2HFoxfRKINlt-FdYZGLxFYtucwm5x894ZFbjiuf-4by0wb2GKnX8sMhwhysEtkffWL3XDrQKBciN_gTThgzGEIwTITuVHN3lQmN42exPihOf/s400/Dibujo5.bmp" border="0" /><br /><p><img id="BLOGGER_PHOTO_ID_5267539062491714994" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 400px; CURSOR: hand; HEIGHT: 295px; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi75TxCYL_5unU3bU_D1vNkZwULJQNlvZt0T2kRLcDgDYcnVc6XB1d6EQ2WE2_ClnP-AvEIOZ7VavaSpyr3T6YXtE1zZxSN8cPXE41Lfs-IR1dTJOBRCAqh5Vi7FteWctEO39lui-w_ps5-/s400/Dibujo4.bmp" border="0" /></p><ol><br /><li><div align="justify"><strong>EJECUTABLE<br /></strong>Se desarrollo en c++ exactamente en wxdev c++ para insertar en la base de datos multimedia se ingresa en la ventana insertar .Para la busquecar en la ventana de busqueda se selecciona el numero de imagenes mas cercanas que se desea buscar ademas se puede visualizar la distancia de cada imagen que devuelve el programa. <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcUcJDvsHfrK0vnG2XUPlr_VJRD3fUjqQ_HjliBos4_FZ8yYr1yx_aQQp3xG5a-DiHrnawt98qeCFZyX092hteI4GbOtyubkcTleefvZke_6r2pxYxvGBIEqj9Z5yV4U837nNTr3DKDrt6/s1600-h/Dibujo1.bmp"><img id="BLOGGER_PHOTO_ID_5267520150423185410" style="FLOAT: left; MARGIN: 0px 10px 10px 0px; WIDTH: 400px; CURSOR: hand; HEIGHT: 307px" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcUcJDvsHfrK0vnG2XUPlr_VJRD3fUjqQ_HjliBos4_FZ8yYr1yx_aQQp3xG5a-DiHrnawt98qeCFZyX092hteI4GbOtyubkcTleefvZke_6r2pxYxvGBIEqj9Z5yV4U837nNTr3DKDrt6/s400/Dibujo1.bmp" border="0" /></a></div></li></ol><br /><br /><br /><br /><br /><br /><br /><br /><p align="center"><a href="http://www.blogger.com/Descargar%20Recuperacion%20de%20Imagenes%20por%20Contenido">Descargar Recuperacion de Imagenes por Contenido</a></p>Oscar Enrique Fernández Asunción, Ingeniero Informático, Universidad Nacional de Trujillohttp://www.blogger.com/profile/07877105547794172771noreply@blogger.com3tag:blogger.com,1999:blog-4751458547939065369.post-84541396082289604072008-09-27T12:53:00.000-07:002008-11-11T12:53:46.823-08:00Subdivisión Doo-Sabin<div align="justify">En la tercera unidad del curso de geometria computacional se vieron 3 algoritmos para subdivisión de objetos 3D (Doo- Sabin, Catmull-Clark, el esquema de Loop) Se implemento un algoritmo para laboratorio el de Doo-Sabin del cual hablare a continuación.<br /></div><ol><li><strong>INTRODUCTION </strong><strong><br />Subdivisión de superficies:<br /></strong>Representación de superficies mediante un mallado<br />Refinado de la malla mediante un proceso iterativo<br />La superficie será igual al límite de refinamientos sucesivos<br /><strong>Aplicaciones:</strong><br />Utilizada en el corto de animación "Geri's Game" (Pixar), y en las películas "Bichos" y "Toy Story 2" (Pixar/Disney). <img id="BLOGGER_PHOTO_ID_5250793348775954914" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 377px; CURSOR: hand; HEIGHT: 162px; TEXT-ALIGN: center" height="164" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj63hvCuHFfVRsTCceUyqAHh0miayZwlh542_sZp4T1KhZq_KkjV4XnfY35oShybr81fovo5JuzOM5QGwP3BSEpJIVJ0ejegwnqin4avv5NzP66gF47afd8EPJ5LpXnqzVpRjMXAmwAiJwG/s400/Dibujo.bmp" width="389" border="0" /><br /><strong>Ventajas de la subdivisión</strong><br />Permiten dibujar superficies de topología compleja<br />Permiten obtener distintos niveles de detalle<br />Son numéricamente estables<br />Sencillas de implementar<br />Se ejecutan (renderizar) directamente</li><br /><br /><li><strong>REGLAS DE DOO-SABIN</strong><br />Se debe crear para cada cara un punto para cada uno de los puntos de la cara.<br />Cada nuevo punto es el punto medio del segmento que une el centroide de una cara con cada uno de sus vértices.<br />Crear con las aristas de todos los puntos internos a una cara una nueva cara.<br />Crear con las aristas de todos los puntos generados de aristas adyacentes una nueva cara.<img id="BLOGGER_PHOTO_ID_5250806677990188098" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizs-TjYFawkHD1ibzARRhJq9xktTzQ_MKKlDpYgZLSE4vbxGjwXdDliRSPDqtqx7ocNyqkmohsBS10rV6B3CA8EZeJZo1TkYgbq84ZqHXpZLzxwdSX7jUodG5fWbceQgQ_Cow1B-THo_pf/s400/cubo.jpg" border="0" /></li><li><div align="justify"><strong>EJECUTABLE</strong><br />Se desarrollo en java, el objeto ya esta ingresado solo pueden variar su forma con el<br />mouse para obtener otros resultados, la aplicacion se desarrollo para 3 iteraciones. </div></li></ol><br /><br /><p align="center"><img id="BLOGGER_PHOTO_ID_5250794715910783586" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhokhW-7YDKJ2vtJhmhDkRtvTDy35nIu-NyREvucXlTF0MsNg30QyTGZUWnWlukBAbenKwSX9xkjW_bHT8rvWElGMYP4CktiL7ImkjTuUOk2sZL_xCkUi9Dd6FYHwJtw0WUtywiKUAtqhiM/s400/doosabin.bmp" border="0" /><br /><a href="http://www.seccperu.org/files/dooo.rar">Descargar Doo-Sabin</a></p>Oscar Enrique Fernández Asunción, Ingeniero Informático, Universidad Nacional de Trujillohttp://www.blogger.com/profile/07877105547794172771noreply@blogger.com1tag:blogger.com,1999:blog-4751458547939065369.post-40730120237142553222008-09-27T09:35:00.000-07:002008-11-11T12:54:25.143-08:00Triangulación de Delaunay<div align="justify">En al segunda unidad del curso de geometría computacional se implemento los algoritmos de triangulación de polinomios (Ear Clipping, triangulación monótona) así como triangulación de una nube de puntos en este caso la triangulación de Delaunay de la que hablare a continuación<br /></div><ol><li><div align="justify"><strong>INTRODUCTION<br /></strong>Se le denomina así por el matemático ruso Boris Nikolaevich Delone (Борис Николаевич Делоне, 1890 - 1980) quien lo inventó en 1934.<br />Es una red de triángulos que cumple la condición de Delaunay. Esta condición dice que la circunferencia circunscrita de cada triángulo de la red no debe contener ningún vértice de otro triángulo.<br /><br /></div></li><li><div align="justify"><strong>CONDICIÓN DE DELAUNAY</strong> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgL8YyjizNSD7qkgFkxqkVgPps6Ly8PQCA34IlCokXSOEY6zjURTX3dS3lyvojOWmGIRRYcBj95NxKZdxCw4POEsr6SEFaC404QV55b8_rpcT9aCY8HgS5ambBUV_9j8DSisf3QUZXZVA3R/s1600-h/1.bmp"><img id="BLOGGER_PHOTO_ID_5250742088071692066" style="FLOAT: right; MARGIN: 0px 0px 10px 10px; WIDTH: 398px; CURSOR: hand; HEIGHT: 189px" height="169" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgL8YyjizNSD7qkgFkxqkVgPps6Ly8PQCA34IlCokXSOEY6zjURTX3dS3lyvojOWmGIRRYcBj95NxKZdxCw4POEsr6SEFaC404QV55b8_rpcT9aCY8HgS5ambBUV_9j8DSisf3QUZXZVA3R/s400/1.bmp" width="350" border="0" /></a><br />La condición de Delaunay dice que una red de triángulos es una triangulación de Delaunay si todas las circunferencias circunscritas de todos los triángulos de la red son vacías. Esa es la definición original para espacios bidimensionales. Es posible ampliarla para espacios tridimensionales usando la esfera circunscrita en vez de la circunferencia circunscrita. También es posible ampliarla para espacios con más dimensiones pero no se usa en la práctica.<br />La arista p1p2 es legal mientras que p3p4 es una arista ilegal porque p2 cae dentro del círculo que pasa por p3p1p4.<br />Cuando se detecte una arista ilegal hay que hacer un intercambio de la arista para convertirla en una legal.<br /><br /></div></li><li><div align="justify"><strong>PROPIEDADES<br /></strong>· La triangulación forma la envolvente convexa del conjunto de puntos.<br />· El ángulo mínimo dentro de todos los triángulos está maximizado.<br />· La triangulación es unívoca si en ningún borde de circunferencia circunscrita hay más que tres vértices.<br /><br /></div></li><li><div align="justify"><strong>ALGORITMOS<br /></strong>·Incremental construction<br />·Divide and conquer<br />·Sweepline<br /><strong>Algoritmo Aleatorio Incremental</strong><br />1. Introducir la nube de puntos P de tamaño n en un gran triángulo conteniendo a dicha nube de puntos Algoritmo Aleatorio Incremental<br />2. Para cada uno de la n puntos de P, elegir pr de forma aleatoria y triangular:<br />2.1. Encontrar el triángulo pipjpk conteniendo a pr<br />2.2. SI pr cae en el interior del triángulo pipjpk ENTONCES añadir aristas desde pr hasta los vértices pi,pj,pk<br />● Legalizar_Aristas (pr, pipj) <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfYwcfA2ftzTrJV5OzTTMt-5SZ260KK4c2aEB4hIfVou0YD2xyjDy6nJhq2WNnGqjTfnyYbB0PN1xL6RcNbJHAjvL8Y9MopNpcRzhVXhUHJIgqDFHHFijD26L-ZV-LO2nsFy7po3mcvoE-/s1600-h/2.bmp"><img id="BLOGGER_PHOTO_ID_5250743967429875842" style="FLOAT: right; MARGIN: 0px 0px 10px 10px; WIDTH: 219px; CURSOR: hand; HEIGHT: 183px" height="171" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfYwcfA2ftzTrJV5OzTTMt-5SZ260KK4c2aEB4hIfVou0YD2xyjDy6nJhq2WNnGqjTfnyYbB0PN1xL6RcNbJHAjvL8Y9MopNpcRzhVXhUHJIgqDFHHFijD26L-ZV-LO2nsFy7po3mcvoE-/s400/2.bmp" width="215" border="0" /></a><br />● Legalizar_Aristas (pr, pjpk)<br />● Legalizar_Aristas (pr, pkpi)<br />2.3. SINO pr cae en la arista pipj , que es incidente a los triángulos pipjpk y pipjpl<br />● Legalizar_Aristas (pr, pipl)<br />● Legalizar_Aristas (pr, plpj)<br />●Legalizar_Aristas (pr, pjpk)<br />● Legalizar_Aristas (pr, pkpi)<br />3. Finalmente eliminar los tres puntos del gran triángulo inicial.<br /><br /></div></li><li><div align="justify"><strong>EJECUTABLE</strong><br />Se desarrollo en java, se ingresan los puntos con el Mouse ya demás tener en cuenta que una ves ejecutado Delaunay ya no se pueden seguir ingresando mas puntos se debe abrir de nuevo la aplicación.<br /></div></li></ol><p align="center"><img id="BLOGGER_PHOTO_ID_5250798176540460258" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhT3fkhntE2zLbMrwYdAib0D0gppT-WC1ctoK6h2MIZRKqLr9qQQZSvfNwcntUGL_j4_smSuWRfpTT-FQIjSHmjn6ioBFzArRsz0YSzswcBX7VJp6PPnrqb2xKR11cfSv14trOEA-8m0O29/s400/3.bmp" border="0" /><a href="http://www.seccperu.org/files/dela.rar">Descargar Delaunay</a><br /><br /></p>Oscar Enrique Fernández Asunción, Ingeniero Informático, Universidad Nacional de Trujillohttp://www.blogger.com/profile/07877105547794172771noreply@blogger.com3tag:blogger.com,1999:blog-4751458547939065369.post-84970213497691865252008-09-20T14:28:00.000-07:002008-09-27T13:54:33.536-07:00Kirkpatrick-Seidel’s<div align="justify">Este algoritmo lo implemente en el curso de Geometria Computacional como trabajo de investigacion de la primera Unidad, la idea del algoritmo la explicare a continuacion pero lo que si se debe tener en cuenta es que la complejidad despues de implementarlo debe ser T(n, h) = O(n lg h) si esto no es asi entonces de nada servira pues para ello existen otros algoritmos mas sencillos pero con mayor complejidad que se implementaron en el laboratorio de este curso ( Graham Scam, Gift wrapping, Algoritmo Incremental, QuikHull, Algoritmo Divide y Venceras) .<br /></div><br /><ol><br /><li><div align="justify"><strong>INTRODUCTION</strong> <img id="BLOGGER_PHOTO_ID_5248224945459881026" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6T6AAy46mlzPlSnpU_6ZU-BXqgKUbOAZQIMnYqW5glB1Ok-UF5veLUaKLh0YEyBqh2FsyKEE2zkJ1dWFKQGWqceJUhSEwismpZuqzLb2QMVdJ5-JXslgypyQOGdjLE630kGLMtn4_Cn9w/s400/a.PNG" border="0" /><em><strong> Figure 1: Casco alto y casco bajo</strong></em><em><br /></em>El algoritmo de Kirkpatrick Seidel se nombra de esa manera por sus inventores, David G. Kirkpatrick y Raimund Seidel. La idea basica de este algoritmo es utilizar la tecnica de dividir y conquistarasi como una poda para hallar la cerradura convexa la cual es tratada como dos algoritmos (algoritmo para el casco alto y algoritmo para el casco bajo) en dos dimensiones vendria a ser la separacion por la vertical del x minimo y el x maximo ( g.1). En realidad los dos algoritmos son muy parecidos por ello se hablara de uno de ellos el algoritmo del casco alto, para este algoritmo se debe hallar la mediana (m) de los puntos P y dividir en dos grupos L y R y hallar un segmento pq donde p pertenece a L y q pertenece a R ( g.2) despues de esto se eliminaran de L los puntos mayores a x(p) y de R los menores a x(q) para volver a calcular el casco alto de cada uno de los grupos restantes L' y R'.<br />Figure 2: Puente superior y mediana <img id="BLOGGER_PHOTO_ID_5248225688145023842" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_dWxDJ0kxNkIxCbUY3Jc_SUiVUlg23_qYtw2hZwnSDn1C2qZpuB5YLkFmwWJslS2ugrxSXAQAaHwuIc6kBoNcLkILQtBgB-A7FMMwoohIrOsLiQIYyLYg3sieS-qCGhm7FU3zCexgKFPx/s400/b.PNG" border="0" /><strong><em> Figure 2: Puente superior y mediana</em></strong></div></li><br /><li><div align="left"><strong>ALGORITMO</strong><br />Es un algoritmo recursivo aqui se presenta el algoritmo para el Casco Alto de igual forma para hallar el Casco Bajo se seguira el mismo algoritmo solo que se utilizaran solo los puntos con menor Y.<br /><img id="BLOGGER_PHOTO_ID_5248231880671531394" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 362px; CURSOR: hand; HEIGHT: 303px; TEXT-ALIGN: center" height="300" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeQRhaZIShdAdpWtzE_CXcDyJOucaZpAye7PvEx0ZZb3gFZ74vGnWFL3Lx9e2ly4CeGVa1C_MA6y2f1Kcj3xMJjUVNjhg5_j9LwsEVX4sfACwDlB_jfjffW8s29917ELU8Jw5GBGs-6Gl0/s400/algoritmo.JPG" width="369" border="0" /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiB3K2VBetKNX5n-VlKF4wJZwLakc-SAQJq7h0VglLvJrhFqxasQzBXlowzSR4YrccAmrnodi2HzEPJKTNu-7auFFV03Xuolz40UjNZkLUSx10ssVSanQn1Zo0I2jOrJhaL5fnSJn3aN0sS/s1600-h/algoritmo.JPG"></a></div></li><li><div align="justify"><strong>ENCONTRAR EL PUENTE SUPERIOR<br /></strong>Para hallar el puente superior debemos escoger del grupo de puntos L un p y del grupo de puntos R un q tal que el y de la interseccion con la mediana sea el mayor de todos ( g.3).<br />Sea: p=(x1, y1) y q=(x2, y2) dos puntos donde p 2 L y q 2 R. Entonces: la ecuacion de la<br />recta pq seria:<br />y-y1= (y2-y1/x2-x1)*(x-x1)<br />Tambien sabemos que el punto de la ecuacion de la recta de la mediana que se intercepta<br />con pq es: (xm, ym) pero sabemos que xm = m , ademas sabemos que el punto (xm, ym)<br />pertenece ala recta pq por ello para hallar el maximo y se obtendria de la siguiente manera:<br />y-y1= (y2-y1/x2-x1)*(x-x1)<br />y-y1= (y2-y1/x2-x1)*(xm-x1)<br />y= (y2-y1/x2-x1)*(xm-x1) +y1</div></li></ol><img id="BLOGGER_PHOTO_ID_5248228265933018738" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZ3_bTmqfeRui2-XniwYb1qOmzRuxo2dwh7CfGHdeWaFrREjH8j7W39XH59dr8wM9rHCaFgCvnXjrOdyQ6wl2SF9Tf64lqncSKm5Zb6AHzKcn5GysHW0jsFXbjLiJc6-IJ14rmCrMdxtZr/s400/c.PNG" border="0" /><br /><strong><em>Figure 3: Puentes superiores posibles</em></strong><br />La idea no termina aqui pues la primera idea seria comparar punto por punto lo que seria O(n^2) pero este paso se debe hacer en O(n) y fue en O(n) que pude implementar este paso.<br /><br /><ul><li><div align="justify"><strong>EJECUTABLE<br /></strong>Se desarrollo en java, se pueden ingresar los puntos mediante eventos del mouse asi como cargando los puntos desde un archivo tambien se podra visulisar el tiempo que demora la ejecucion del algoritmo. En los archivos hay 1000 , 10 000 , 100 000, 500 000, 1 000 000 puntos respectivamente. Com 1 000 000 se daran cuenta que se optiene un buen tiempo al ejecutar el algoritmo O(n lg h) .</div></li></ul><img id="BLOGGER_PHOTO_ID_5250724491717145698" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 413px; CURSOR: hand; HEIGHT: 286px; TEXT-ALIGN: center" height="310" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUtOoVmemST5RMB-bohXR7wPM17YbZ70RMMRFj7pnLekRoqbS2bERRTAyovmMtMSBpSuN-MmEu3YRXu1PrbIXj6L7t_odmy4Bj5fanIIUdTnnzfPtx7vv9b2iDa9p6W1Y16BiKHkRVNWYT/s400/kirp.bmp" width="426" border="0" /> <p align="center"><a href="http://www.seccperu.org/files/parte1.rar">Descargar Kirkpatrick-Seidel’s parte1</a><br /></p><p align="center"></p>Oscar Enrique Fernández Asunción, Ingeniero Informático, Universidad Nacional de Trujillohttp://www.blogger.com/profile/07877105547794172771noreply@blogger.com3tag:blogger.com,1999:blog-4751458547939065369.post-51371366906658021312008-04-27T15:35:00.000-07:002009-04-12T19:57:12.451-07:00Programacion Logica : swi-prolog , Interfaces<p align="justify"><span style="color:#000000;">Este articulo va destinado para las personas que tienen nociones básicas en programacion lógica o han manejado otro entorno programacion logica diferente al swi-prolog ejemplo visual prolog etc, Pero creo que no es tan dificil de entender lo que se les mencionara a continuacion. Lo ideal es que dado unas pequeñas nociones y funciones puedan utilizar la ayuda o demás herramientas para lograr un mejor entendimiento de todo lo que se mencionara a continuación <a href="http://jc-info.blogspot.com/">Primeros pasos en swi-prolog en el blog de Jorge Valverde Revaza</a>.<strong> </strong></span></p><br /><ol><br /><li><div align="justify"><span style="color:#000000;"><strong>Descargar Swi-Prolog :</strong><br /><a href="http://gollem.science.uva.nl/cgi-bin/nph-download/SWI-Prolog/w32pl5654.exe">http://gollem.science.uva.nl/cgi-bin/nph-download/SWI-Prolog/w32pl5654.exe</a>.<br /></span></div></li><li><div align="justify"><strong>Manejar Entorno de trabajo:<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg97JY4vai97LrQ-pzOPgz040Lp5XxlNSwTdRL9mwYQrnhsnKPrjztWlY24yifU7YPVhnZJt8s9QvcFnw2Vr61ikTbhQJ74elwYR3OY0DbBh-EeTt9Z1IR_LxZNkY30BptZGa8g4Bu6tO1L/s1600-h/Dibujo.JPG"><img id="BLOGGER_PHOTO_ID_5194075400405505762" style="FLOAT: right; MARGIN: 0px 0px 10px 10px; WIDTH: 400px; CURSOR: hand; HEIGHT: 276px" height="324" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg97JY4vai97LrQ-pzOPgz040Lp5XxlNSwTdRL9mwYQrnhsnKPrjztWlY24yifU7YPVhnZJt8s9QvcFnw2Vr61ikTbhQJ74elwYR3OY0DbBh-EeTt9Z1IR_LxZNkY30BptZGa8g4Bu6tO1L/s400/Dibujo.JPG" width="400" border="0" /></a><br /></strong>Para esto abrir swi-Prolog aparecerá algo así , para tener un editor de programación lo único que debemos hacer es seleccionar de los botones de arriba Settings - User init file.. y nos aparecerá una nueva ventana cerramos la ventana y ahora si procedemos a file - New para crear un nuevo proyecto (la operación anterior algunos utilizan emacs.) de igual manera si se desea abrir un .pl doble clic sobre el .pl después Settings - User init file.. y la cerramos file - edit nombre.pl y aparecerá tu proyecto.<br /><br /></div></li><li><div align="justify"><strong>Sintaxis de swi-Prolog:<br /></strong>Bueno la sintaxis de swi-prolog es igual que cualquier otro entorno de programcion logica .<br />Cualquier programa en Prolog tiene que estar escrito en un fichero de texto plano (sin formato). Lamanera mas sencilla es usar el Bloc de Notas. Dicho archivo debe poseer la extensin ”.pl” para indicar que contiene codigo fuente de Prolog.<br />Un programa Prolog esta formado con un conjunto de hechos y de reglas junto con un objetivo. El archivo del codigo fuente de Prolog contendra el conjunto de hechos y de reglas y el objetivo sera lanzado desde el shell de SWI-Prolog.<br />Existen ciertas consideraciones sobre la sintaxis de Prolog:<br /><strong>1. Variables:<br /></strong>El identificador de una variable tendra que tener su primera letra en mayusculas.<br />Ej: X, Atapuerca, Cobaltina, RADgtfCdf<br /><strong>2. Constantes:</strong><br />La primera letra de una constante deber´a estar escrita en min´usculas.<br />Ej: a, incienso, roberto, rADgtfCdf<br />Tambi´en se consideran constantes a los n´umeros,<br />Ej: 1, 5.02, 0.7<br />las palabras entre comillas simples<br />Ej: ’a’, ’A’, ’a a’<br />y la lista vacıa [ ].<br /><strong>3. Funciones:</strong><br />Al igual que las constantes, su primera letra debe ser una minuscula. Debera estar seguido de un conjunto de terminos (otras funciones, variables o constantes) encerrados entre parentesis.<br />Ej: f(c,X), conc arbol(Hijo Izq, Raiz, Hijo Der), rADgtfCdf(RADgtfCdf, rADgtfCdf)<br /><strong>4. Predicados:<br /></strong>Su sintaxis es la misma que la de las funciones aunque, por su localizacion dentro de la clausula (es decir, dentro del programa Prolog), el compilador los identificara como tal, y no como funciones.<br />Ej: f(c,X), conc arbol(Hijo Izq, Raiz, Hijo Der), rADgtfCdf(RADgtfCdf, rADgtfCdf)<br />Tambien existe la posibilidad de tener predicados 0-arios.<br /><strong>5. Hechos:</strong><br />Son clausulas de Horn que poseen un unico predicado en la cabeza y ninguno en el cuerpo. Tienen la siguiente forma en sintaxis de logica de primer orden: P<br />En Prolog no se escribe la flecha sino que se pone un punto al final: p.<br />donde p es un predicado y tiene que seguir su sintaxis. Ej:<br />padre(aaron, maria).<br />compositor(shostakovich).<br />shostakovich(compositor).<br /><strong>6. Reglas:<br /></strong>Son clausulas de Horn que poseen un ´unico predicado en la cabeza y uno o m´as en el cuerpo.<br />Tienen la siguiente pinta:<br />P← Q1,Q2,Q3 escritos en sintaxis clausular o<br />P←Q1 ^ Q2 ^ Q3 escritos en sintaxis de logica de primer orden.<br />En Prolog la flecha se sustituye por ”:-”, las conectivas conjuntivas se escriben como comas ”,” y la regla termina en punto:<br />p :- q1, q2, q3.<br />donde, al igual que los hechos, p y q1, q2 y q3 son predicados. Ej:<br />cuadrado(X) :- poligono(X), numero_lados(X,4).<br /><strong>7. Objetivos:<br /></strong>Son clausulas de Horn que no poseen ningun predicado en su cabeza:<br />&← Q1,Q2,Q3<br />Los predicados se escriben separados por comas y terminados en punto. Solo pueden sen lanzados desde el shell de SWI-Prolog.<br />?- padre(X, Y),padre(Y, Z).<br /></div></li><li><div align="justify"><strong>Compilacion y ejecucion en swi-prolog:<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhi7ATBJzOknbnF-64heZz-PR3HN51cYxRb-aM7aeMQmJWp-FdBJvDWz7_FfCE0ZVlmrn4A7qcoxj2ijsaiGbbB8KPK-Rj9tz9jtyTe8AdEgLay3V9fE96h6DvVf0LYyM77u9es2k5MWnR-/s1600-h/Dibujo1.JPG"><strong><img id="BLOGGER_PHOTO_ID_5194080142049400562" style="FLOAT: right; MARGIN: 0px 0px 10px 10px; CURSOR: hand" height="337" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhi7ATBJzOknbnF-64heZz-PR3HN51cYxRb-aM7aeMQmJWp-FdBJvDWz7_FfCE0ZVlmrn4A7qcoxj2ijsaiGbbB8KPK-Rj9tz9jtyTe8AdEgLay3V9fE96h6DvVf0LYyM77u9es2k5MWnR-/s400/Dibujo1.JPG" width="400" border="0" /></strong></a><br /></strong>La codificacion en swi- prolog es la misma que todos los editores de prolog solo que aquí no declaras la variables que vas a utilizar, las funciones básicas serian:<br />write, fail, nl, is ,!,:- dynamic, retract, assert, etc <em>;<br /><br /></em>Algunos códigos como disktra , autómata, gramaticas, pequeño sistema experto, operaciones con listas , ordenación por mezcla selección inserción, vectores , matrices, problemas con recursion, torre de hanoi, búsquedas , etc, son los que se puedieron desarrollar en el laboratorio del curso de programacion logica dictado por Ivan sipiran.<br />Para complilar un proyecto Compile-Compile buffer y para ejecutarlo en la consola de swi-prolog (figura anterior) escribir nombreReglaoHecho. y enter. </div></li><br /><br /><br /><li><div align="justify"><strong>Todas las soluciones a un objetivo:</strong><br />Existen predicados que no se paran cada vez que llegan a una hoja exito en el arbol de vuelta atras sino que realizan todo el arbol que esta por debajo de un objetivo dado y guardan las soluciones (unificaciones) en una lista.<br />findall(+Template, +Goal, -Bag): realiza todo el arbol de backtracking del objetivo Goal. Cada vez que llega a un exito unifica las variables con la plantilla Template e introduce el resultado en la lista Bag.<br />5 ?- listing.<br />dios_egipcio(amon).<br />dios_egipcio(anubis).<br />dios_egipcio(apis).<br />dios_egipcio(ra).<br />Yes<br />6 ?- findall(X,dios_egipcio(X), L).<br />X = _G362<br />L = [amon, anubis, apis, ra]<br />yes<br />bagof(+Template, +Goal, -Bag): identico a findall/3 excepto que si el objetivo posee variables libres entonces primero probara la unificacion con esas variables libres y despues realizara el arbol de vuelta atras para cada una de esas unificaciones, parando cada vez.<br />?- listing.<br />vida(carlos_III, 1716, 1788).<br />vida(carlos_IV, 1748, 1819).<br />vida(fernando_VII, 1784, 1833).<br />yes<br />?- bagof([A,B], vida(A, B, C),L).<br />A = _G371<br />B = _G374<br />C = 1788<br />L = [[carlos_III, 1716]] ;<br />A = _G371<br />B = _G374<br />C = 1819<br />L = [[carlos_IV, 1748]] ;<br />A = _G371<br />B = _G374<br />C = 1833<br />L = [[fernando_VII, 1784]] ;<br />No<br />Si no queremos que se pare cada vez que encuentre una unificacion debemos usar el sımbolo ˆ como<br />en el ejemplo:<br />?- bagof([A,B], C^vida(A, B, C),L).<br />A = _G383<br />B = _G386<br />C = _G391<br />L = [[carlos_III, 1716], [carlos_IV, 1748], [fernando_VII, 1784]] ;<br />No<br />setof(+Template, +Goal, -Set): igual que bagof/3 pero la lista Bag es devuelta ordenada y sin duplicados.<br /></div></li><li><div align="justify"><strong>Interfaces en swi-prolog usando XPCE:<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLdkWUWem-Qpbwa2cVSZi139XtQu4iAFxZhupkLkJ_oKYlFrzV4hirr5n4Xjalp63YoUdjilKVh6ltI6j_0M6-EzF5LvBJvq_ZWiL8pNkChgKHsdf-Ly1Cia4lHORwZfAzD442UXMDHGu-/s1600-h/Dibujo2.JPG"><img id="BLOGGER_PHOTO_ID_5194393704726779698" style="FLOAT: right; MARGIN: 0px 0px 10px 10px; CURSOR: hand" height="185" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLdkWUWem-Qpbwa2cVSZi139XtQu4iAFxZhupkLkJ_oKYlFrzV4hirr5n4Xjalp63YoUdjilKVh6ltI6j_0M6-EzF5LvBJvq_ZWiL8pNkChgKHsdf-Ly1Cia4lHORwZfAzD442UXMDHGu-/s400/Dibujo2.JPG" width="255" border="0" /></a></strong><br />La creacion de interfaces en swi-prolog no es tan complicada como podriamos imaginarnos por ejemplo tenemos lo siguiente :<br />primerVentana:-new(D, dialog('Nombre de tu ventana')), send(D, open).<br /><br /><strong>Existen cuatro predicados basicos que te permiten interactuar con los objetos de swi-prolog :</strong><br /><br />?? new(?Reference, +NewTerm): Este predicado recoge dos parámetros, el primero recogería la referencia que se le asigna al nuevo objeto, ya que new se usa para crear objetos. El segundo parámetro le indicaría el objeto que se quiere crear.<br /><br />?? send(?Receiver, +Selector(...Args...)): El primer parámetro del predicado es una referencia al objeto que deseemos enviarle un mensaje. El segundo parámetro indicará el método al que queremos invocar, lo cual indicaremos junto a los argumentos que queremos enviarle al método.<br /><br />?? get(?Receiver, +Selector(+Argument...), -Result): Los dos primeros parámetros tienen el mismo significado que para send, sin embargo el último parámetro sirve para recoger el valor que nos devuelva el método que hallamos invocado.<br /><br />?? free(?Reference): libera la memoria asociada al objeto que se le indica en el primer parámetro.<br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpiPaiIgort6mIgHKFeYxVJkj860tjOtJSy1X1CE8gsLzaefKQxDmcwEadPnywA3ZUU7e0aWhgyoYShfGlYlXjisBDAvbdKeVNs7bD3BnZx47o5cKLoBRbjta2ov3CLCoR_bxtH6Mc8J_S/s1600-h/interfaz.JPG"><img id="BLOGGER_PHOTO_ID_5194401066300725058" style="FLOAT: right; MARGIN: 0px 0px 10px 10px; CURSOR: hand" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpiPaiIgort6mIgHKFeYxVJkj860tjOtJSy1X1CE8gsLzaefKQxDmcwEadPnywA3ZUU7e0aWhgyoYShfGlYlXjisBDAvbdKeVNs7bD3BnZx47o5cKLoBRbjta2ov3CLCoR_bxtH6Mc8J_S/s400/interfaz.JPG" border="0" /></a><strong>Los objetos que podemos manejara en swi-prolog son:<br /></strong>button<br />label<br />menu<br />menu_bar<br />menu_item<br />popup<br />slider<br />window<br />int_item<br />editor<br />text<br />text_item<br />picture<br />etc.<br /><br />Cada uno de estos objetos como vimos en el ejemplo primeraVentana se alamcenan en variable por intuicion podemos concluir que para agreagar un boton a una ventana primero crearemos ambos objetos y despues agregaremos la variable de un boton a la variable de la ventana.<br /><br /><strong>Todos estos objetos tienen atributos como:</strong><br />size<br />display<br />margin<br />colour<br />style<br />background<br />font<br />etc.<br /><br /><strong>Explicare algunos Objetos con mayor detalle:</strong><br /><br /><strong>DIALOG<br /></strong>Esta es la clase básica para crear dialogos.<br /><em><strong>Constructor:<br /></strong></em>dialog(label=[name], size=[size], display=[display])<br />name: indica el titulo a la ventana<br />size: es de tipo size y sirve para indicar el tamaño de la ventana display: indica donde queremos que se visualize (mejor no tocar este parametro si no sabemos que estamos haciendo) Podemos observar que todos los parametros son opcionales, aunque siempre es bueno ponerle un titulo a la ventana Así, como ejemplo crearemos un dialogo con titulo ‘Titulo del dialogo’ y de tamaño 440 x 320.<br />new(D, dialog(‘Titulo del Dialogo’, size(440, 320)) ),<br /><em><strong>Métodos:<br /></strong></em>Esta clase dispone de varios métodos que pueden resultar interesantes, entre ellos tenemos:<br />append(Objeto): Insertaria el objeto Objeto dentro del dialogo, visualizandolo en<br />el mismo, por ejemplo sirve para insertar un boton o cualquier otra cosa, como en el siguiente ejemplo:<br />send(D, append(button(‘Boton 1’)))<br />open(): abre la ventana de diálogo visualizandola en pantalla:<br />send(D, open),<br />destroy(): cierra la ventana de diá logo visualizada en pantalla:<br />send(D, destroy),<br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSIrBDw2PMoqhxQ2WohsYyueQRQ7FOE7A5sd3FqwqlNgF_U-yujElCSJN4qKY4ZPFCd-WgG7T04NOqg6AIWEzeCXpwpmwyvRGdA8L7jcVmlNs2Vcf6iQMt-uGEhm9OyNCIXKOEGwwSMAK7/s1600-h/damas.JPG"><img id="BLOGGER_PHOTO_ID_5194428910573705058" style="FLOAT: right; MARGIN: 0px 0px 10px 10px; CURSOR: hand" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSIrBDw2PMoqhxQ2WohsYyueQRQ7FOE7A5sd3FqwqlNgF_U-yujElCSJN4qKY4ZPFCd-WgG7T04NOqg6AIWEzeCXpwpmwyvRGdA8L7jcVmlNs2Vcf6iQMt-uGEhm9OyNCIXKOEGwwSMAK7/s400/damas.JPG" border="0" /></a><br /><strong>BUTTON<br /></strong>Esta es la clase básica para crear botones<br /><strong><em>Constructor:<br /></em></strong>button(name=name, message=[code]*, label=[name] )<br />name: indica el nombre del boton (si no se especifica la etiqueta que queramos que tenga el boton, entonces adoptará una etiqueta con el mismo texto que name)<br />message: indica el mensaje o acción que queremos que sea ejecutado cuando pulsemos sobre el botón con el ratón.<br />label: Indica la etiqueta que queremos que se muestre en el boton.<br />new(Boton, button(‘Salir’, message(Dialogo, quit)))<br /><br /><strong>LABEL</strong><br />Esta es la clase básica para crear etiquetas de texto<br /><strong><em>Constructor:</em></strong><br />label(name=[name], selection=[stringimage], font=[font])<br />name: indica el nombre de la etiqueta<br />selection: puede ser una cadena o una imagen que queremos que sea mostrada en el lugar donde aparece la etiqueta.<br />font: permite indicar la fuente en la que queremos mostrar el texto<br />new(L, label(nombre, ‘texto que queramos que sea mostrado’)),<br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3xKNt6BT_wVZ2lDqmBdP_Hwu2eSr-p4sO1GW0-udAzxSQ8BdjZL1HY3VTCLjcrvVFOhtsIlPi19B6fW-YapIvv-WOvB83uqJWjJSVsBkImzF7ABBxYMfNkBr_8a_Uag8hc-bWjiLCPgUt/s1600-h/Snake.JPG"><img id="BLOGGER_PHOTO_ID_5194429129617037170" style="FLOAT: right; MARGIN: 0px 0px 10px 10px; CURSOR: hand" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3xKNt6BT_wVZ2lDqmBdP_Hwu2eSr-p4sO1GW0-udAzxSQ8BdjZL1HY3VTCLjcrvVFOhtsIlPi19B6fW-YapIvv-WOvB83uqJWjJSVsBkImzF7ABBxYMfNkBr_8a_Uag8hc-bWjiLCPgUt/s400/Snake.JPG" border="0" /></a><br /><strong>WINDOW</strong><br />Esta clase sirve para crear ventanas donde dibujar o poner otros objetos graficos<br /><strong><em>Constructor:<br /></em></strong>window(label=[name], size=[size], display=[display])<br />name: indica el nombre de la ventana<br />size: indica el tamaño que queremos tenga la ventana<br />display: indica donde queremos que aparezca (recomendamos no usar este parametro)<br />Por ejemplo para crear una nueva ventana (de gráficos) de tamaño 320x200 pixels new(W, window(‘nombre ventana’, size(320, 200)),<br /><strong><em>Métodos:</em></strong><br />Para esta clase nos interesarán básicamente los métodos ‘display’ y ‘flush’: display(figure, point): sirve para mostrar una figura en un lugar determinado de la ventana una determinada figura (que por ejemplo puede ser una imagen) y point que indicará las coordenadas (x,y) de la ventana donde queremos que se muestre.<br />El siguiente ejemplo mostraría la figura Figure en la posicion (22, 32) de la ventana W.<br />send(W, display, Figure, point(22,32))<br />flush(): sirve para redibujar la venana que invoca al método, es decir, si estamos realizando una serie de llamadas y no está en el bucle principal de la ventana, entonces podemos llamar a este método para redibujar la ventana y los elementos que hayamos creado o movido.<br />send(W, flush)<br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsW_3Ud2FmUfTI16w8MYBmgxsNBvItf_UyK_sXjRUpkqqF4LXNihU25lBSS5F3h1iNuz2Ut-45OmMy0ggReVatyN3LaQpc7VwBb4FoCBowGLkDhj1yc5JcX84-vbDEQ4qE50mB4KXjpVY8/s1600-h/tetris.JPG"><img id="BLOGGER_PHOTO_ID_5194483649931892626" style="FLOAT: right; MARGIN: 0px 0px 10px 10px; CURSOR: hand" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsW_3Ud2FmUfTI16w8MYBmgxsNBvItf_UyK_sXjRUpkqqF4LXNihU25lBSS5F3h1iNuz2Ut-45OmMy0ggReVatyN3LaQpc7VwBb4FoCBowGLkDhj1yc5JcX84-vbDEQ4qE50mB4KXjpVY8/s400/tetris.JPG" border="0" /></a><br /><strong>Otros predicados y funciones importantes serian:</strong><br />timer: new( timer(0.2,'Aqui lo que se ejecutaro cad cierto tiempo')<br /><br />declarar variables globales: :- pce_global(@'aquinombre varglobal', new('objeto que sera global')).<br /><br />ubicacion de objetos dentro de otro objetos: right ,below ,next_row<br /><br />para cambiar forma de cursor: new(cursor('nombre del nuevo cursor')<br /><br />para retornar y esperar confirmacion de un objeto: return confirm<br /><br />para ejecutar predicados con parametros : message,?selection ejemplo-> message(@prolog, nombrepredicado, TI?selection)<br /><br />retrazar una ejecucion: sleep(10)<br /><br />etc. <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcBeHFClaiFmrDrHjgu50NJ6OVOypBP2ULOhnRw9ttoHw9kFJ3JReySn_bnagWVJaYTBaDK-P7TeX7aDpvq1s8-qEyI0bQWprartd3Tx2Ea9vAIpqrCYZ2XTLDHBWi7ykCpeCwnYnDYpA0/s1600-h/tres.JPG"><strong><img id="BLOGGER_PHOTO_ID_5194429550523832194" style="FLOAT: right; MARGIN: 0px 0px 10px 10px; CURSOR: hand" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcBeHFClaiFmrDrHjgu50NJ6OVOypBP2ULOhnRw9ttoHw9kFJ3JReySn_bnagWVJaYTBaDK-P7TeX7aDpvq1s8-qEyI0bQWprartd3Tx2Ea9vAIpqrCYZ2XTLDHBWi7ykCpeCwnYnDYpA0/s400/tres.JPG" border="0" /></strong></a><br /><br /><strong>Manejo de eventos:</strong><br />Para manejar los eventos de mouse como los de teclado aqui les dejo su estructura .<br />Para mouse:<br />click_gesture<br /><br />Para teclado:<br />key_binding<br /><br />Algunos eventos:<br />handler<br />handler_group<br />key_binding<br />click_gesture<br />connect_gesture<br />move_gesture<br />move_outline_gesture<br />resize_gesture<br />resize_outline_gesture<br /><br /><strong>Manejo de imagenes :<br /></strong>swi-prolog te permite manejar diferentes formatos de imagenes como por ejemplo JPEG, GIF, BMP y PNM.<br />Para utilizar las imagenes primero tenemos que indicar el directorio en donde se encuentran<br /><br />:-pce_image_directory(‘direccion de la carpeta de imagenes ’)<br /><br />despues procedemos a seleccionar el nombre de la imagen:<br /><br />resource(fondo, image, image(‘nonbre de la imagen’)).<br /><br />Para poder mostrar la imagen fondo en un dialogo primero debemos primero debemos pasar la imagen a Bitmap para luego si mostrarla en el dialogo o ventana.<br />Para mover imagenes tenemos los siguientes atributos:<br /><br />send(Figure, move, point(X, Y)).<br />send(Figure, relative_move, point(X, Y)).<br /><br />Las imagenes se comportan igual que cualquier objeto visto anteriormente y se les puede agregar eventos de mouse como de teclado.<br /><br /><strong>Funciones para un entorno grafico:<br /></strong>La<strong> </strong>principales funciones para dibujar con swiprolog serian:<br />arrow<br />bezier<br />bitmap<br />box<br />circle<br />ellipse<br />arc<br />line<br />path<br />text<br />etc.<br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3gh5db2P16OAXkdjA10V0gEKPxhAMCZ_l_Xp-KuGm-W9FCGRUhyJu6vXQtw1AH3CtvuFQwquUGY_qDLALxe7Vf8B77nyrBDXXB1yVsfc6BWBvU4j_YFclrdNlAJStLMgcw85rNJZRqwSn/s1600-h/Automata.JPG"><img id="BLOGGER_PHOTO_ID_5194428420947433298" style="FLOAT: right; MARGIN: 0px 0px 10px 10px; CURSOR: hand" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3gh5db2P16OAXkdjA10V0gEKPxhAMCZ_l_Xp-KuGm-W9FCGRUhyJu6vXQtw1AH3CtvuFQwquUGY_qDLALxe7Vf8B77nyrBDXXB1yVsfc6BWBvU4j_YFclrdNlAJStLMgcw85rNJZRqwSn/s400/Automata.JPG" border="0" /></a><br /><strong>Creacion de ejecutables swi-prolog:<br /></strong>A continucaion un codigo para crear ejecutables :<br /><br />save(Exe):- pce_autoload_all, qsave_program(Exe,[ emulator(swi('bin/xpce-stub.exe')), stand_alone(true), goal(main) ]).<br /><br /><strong>Descargar ejecutables que desarrolle para el curso de programacion logica en swi-prolog:<br /></strong>Tan solo debo hacerles recordar que los ejecutables de swi-prolog no son tan buenos como quisieramos pues su ejecucion se hase un poco pesada.<br />Para ejecutar algun ejecutable primero descargar la carpeta Bin dentro de ella deberan de poner los ejecutables y posteriormente daran doble click sobre cada uno respectivamente.<br /><br /><a href="http://cid-3d37909d7ae99902.skydrive.live.com/self.aspx/blogger-oefa/bin.rar">Descargar Carpeta Bin</a><br /><br /><a href="http://cid-3d37909d7ae99902.skydrive.live.com/self.aspx/blogger-oefa/TresRaya-OscarFernandezAsuncion.rar">Descargar Tres raya swi-prolog</a><br /><a href="http://cid-3d37909d7ae99902.skydrive.live.com/self.aspx/blogger-oefa/Snake-OscarFernandezAsuncion.rar">Descargar Snake swi-prolog</a><br /><a href="http://cid-3d37909d7ae99902.skydrive.live.com/self.aspx/blogger-oefa/SISTEMAEXPERTO-OscarFernandezAsuncion.rar">Descargar Sistema Experto swi-prolog</a><br /><a href="http://www.blogger.com/Descargar%20Damas%20swi-prolog">Descargar Damas swi-prolog</a><br /><a href="http://www.blogger.com/Descargar%20Automata-redPetri%20swi-prolog">Descargar Automata-redPetri swi-prolog</a><br /><a href="http://www.blogger.com/Descargar%20Tetris%20swi-prolog">Descargar Tetris swi-prolog </a><br /><br /></div></li><br /><li><div align="justify"><strong>Archivos y Bases de datos en swi-prolog:<br /></strong>Para archivos seria:<br />Escritura: tell(achivo.txt'), write(primero.'), nl, write('segundo.'), nl, told.<br />Lectura: see('archivo.txt'), read(P), read(S).<br /><br />Para base de datos mysql swi-prolog le dejo un pdf ojala les sea de utilidad:<br /><br /><a href="http://weblogs.inf.udp.cl/nboettcher/uploadfilecat_download/5.">Tutorial mysql con swi-prolog</a><br /></div></li><br /><li><div align="justify"><strong>Conectar Java con swi-prolog:<br /></strong>Los pasos serian en si los siguientes:<br />agregar alas variables de entorno del sistema operativo los siguientes direcciones talvez las direcciones no son las mismas buscar y poner la direccion indicada de cada uno si no conecta reiniciar la maquina o volver a intentar todo de nuevo.<br /><br />path=C:\Archivos de programa\Java\jdk1.5.0_09\bin;%path%<br />path=C:\Archivos de programa\Java\jdk1.5.0_09\lib\tools.jar;%path%<br />path=C:\Archivos de programa\Java\jdk1.5.0_09\jre\lib\rt.jar;%path% path=C:\Archivos de programa\pl\bin;%path%<br />path=C:\Archivos de programa\pl\lib\jpl.jar;%path%<br /><br /><em>Aqui les dejo un codigo de java-swiprolog que se encuentra en la ayuda de swi-prolog . Tambien lo pueden encontrar en C:\Archivos de programa \pl\doc\packages\ examples \jpl \java\Family</em> </div></li><p align="left"><a href="http://www.seccperu.org/files/Family.rar">Descagar codigo de Family</a><br /></p><p align="left"><em>Tambien unos ejemplos que encontre en internet para la coneccion java con swi-prolog<br />ojala les sea de utilidad (son de calculadora y tictactoe). </em></p><p align="left"><em><a href="http://cid-3d37909d7ae99902.skydrive.live.com/self.aspx/blogger-oefa/prolo%20java%20-swiprolog.rar">Descargar Ejemplos java con swi-prolog</a><br /></em><br /><br /></p><li><div align="justify"><strong>Sockets en swi-prolog:<br /></strong>Para el manejo de sockets en swi-prolog ai les dejo un codigo que encontre y me sirvio , ojala les ayude a comprender un poco mas sobre este tema de sockes :<br /><br />%--------------Servidor.pl-----------------------<br />server(Port):- tcp_socket(Socket), tcp_setopt(Socket, reuseaddr), tcp_bind(Socket, Port), tcp_listen(Socket, 0), tcp_open_socket(Socket, InStream, _OutStream), add_stream_to_pool(InStream,get_requests_from_clients(Socket)), stream_pool_main_loop.<br />get_requests_from_clients(Socket):- trim_stacks, tcp_accept(Socket, ClientSocket, ClientIP), tcp_open_socket(ClientSocket, InStream, OutStream), add_stream_to_pool(InStream,get_request(InStream,OutStream,ClientIP)).<br />get_request(InStream,OutStream,_ClientIP):- catch( read(InStream, Request), _, (writeln(error1), close(InStream), close(OutStream),delete_stream_from_pool(InStream), fail) ),<br />close(InStream),<br />( Request==end_of_file -> ( writeln(error2),close(OutStream), delete_stream_from_pool(InStream),fail) ; true ),<br />process(Request,Answer),<br />catch( (write_canonical(OutStream, Answer), write(OutStream, '.\n')), _, (writeln(error3), close(OutStream), delete_stream_from_pool(InStream),fail) ),<br />close(OutStream),<br />delete_stream_from_pool(InStream).<br />get_request(_InStream,_OutStream,_AgentIP).<br />process(Message,test_ok(Message)).<br />:-prolog_ide(thread_monitor), thread_create(server(4000),_, [alias(server),detached(true)]).<br /><br /><br />%------ ------Clientes.pl ---------------<br />create_clients:- between(1,8,N), term_to_atom(client(N),Client), thread_create(client(N), _, [alias(Client),detached(true)]), fail.create_clients.<br />client(N):- Port is 4000+N, between(0,10000,F), sleep(0.0001), once( request(client(ip(127,0,0,1),Port), server(ip(127,0,0,1), 4000),hello_world(F)) ), fail.client(N):- writeln(client_finished(N)).<br />request(client(_ClientIp,ClientPort), server(ServerIp,ServerPort),Message):- tcp_host_to_address(Host,ServerIp),<br />repeat, tcp_socket(Socket), tcp_setopt(Socket, reuseaddr),<br />catch( tcp_connect(Socket, Host:ServerPort), _, (writeln(error(ClientPort,' Client cannot tcp_connect.')),tcp_close_socket(Socket),fail) ),<br />tcp_open_socket(Socket, ReadFd, WriteFd),<br />catch( (write_canonical(WriteFd,Message), write(WriteFd, '.\n')), _, ( writeln(error(ClientPort,' Client cannot tcp_connect.')),tcp_close_socket(Socket),fail) ),<br />close(WriteFd),<br />wait_for_input([ReadFd], [ReadFd], 0),<br />catch( read(ReadFd,Answer), _, ( writeln(error(ClientPort,' Client cannot tcp_connect.')), close(ReadFd),fail) ),<br />close(ReadFd),<br />writeln(answer(ClientPort,Answer)).<br />:-create_clients.</div></li></ol><br /><p></p>Oscar Enrique Fernández Asunción, Ingeniero Informático, Universidad Nacional de Trujillohttp://www.blogger.com/profile/07877105547794172771noreply@blogger.com38