Distancia de un punto a un segmento, primera parte

Julio 6, 2008 by luisrey

Uno de los problemas que he encontrado para seguir con mi programa de dibujo es ¿Como detecto que se ha hecho clic en una recta? Al principio creí encontrar la solución en la función containsPoint: de la clase NSBezierPath. Pero para mi desgracia solamente funciona con caminos cerrados (y una recta no esta muy cerrada que digamos). Para más desgracia una busqueda en google no encontro nada en castellano. Siempre aparecia como encontrar la distancia de un punto a una recta. Al final he encontrado información en inglés (que extraño ¿no?) y he decidido apuntar lo que he aprendido aquí.

Algo de matemáticas…

En este punto es importante que tengas unos conocimentos previos de matemáticas tales como puntos, vectores, rectas, producto escalar de vectores y distancias. Si no es el caso es muy difícil que puedas entender la explicación. Vuelve cuando hayas hecho los deberes.

Encontrar la distancia entre un punto y una recta es fácil:

Por ejemplo puede utilizarse la siguiente fórmula que utiliza el producto vectorial de dos vectores:

En dos dimensiones basta conocer las coordenadas de los puntos A(Ax, Ay), B(Bx, By) y C(Cx, Cy):

Nota: He “ignorado” algunos detalles, el producto vectorial solamente tiene sentido en tres dimensiones y realmente lo que interesa és el módulo del vector resultante, pero crear un vector 3D a partir de un vector 2D es trivial y puede comprobarse que el resultado funciona.

En cualquier caso lo que me interesa no es la distancia punto-recta sino punto-segmento, y si generalmente la fórmula anterior parece servir, fracasa en ejemplos como el siguiente:

En este ejemplo la fórmula proporciona una distancia a la recta, pero no al segmento. En este caso la distancia que nos interesa encontrar es entre los puntos B y C. Esto nos indica que calcular la distancia entre un punto y un segmento es algo más complicado y habrá que escoger fórmulas diferentes según la posición del punto respecto al segmento.

La solución pasa por encontrar el punto P de la recta que esta más cercano al punto C y luego comprobar si esta dentro del segmento:

En cualquier recta un punto cualquiera P(Px, Py) puede encontrarse a partir de un parámetro u y el vector que une los punto A y B, como:

Para encontrar el punto P se puede utilizar el producto escalar:

A partir de las ecuaciones anteriores (y un cierto trabajo) se puede obtener una fórmula que permite obtener el parámetro u:

  • Si el valor de u esta entre 0 y 1 el punto P estará dentro del segmento. Para calcular la distancia entre el punto C y el segmento sólo hay que calcular la distancia entre P y C.
  • Si es mayor que 1, C ha sobrepasado el segmento por B. La distancia entre el punto y el segmento será la distancia entre los puntos B y C.
  • En cambio si u es menor que 0, el punto C no ha llegado al segmento. La distancia será la distancia entre los puntos A y C.

Fácil. No…. (Aquí uno de mis queridos profesores de la facultad decia que era “trivial”).

Un último detalle, el único problema a nivel de crear el algoritmo estará en el denominador, si A y B son el mismo punto en la fórmula nos aparecera una desagradable división por cero.

Y hasta aquí la introducción matemàtica. Próximamente el código.

Más información

Bloc d’Apple en català

Julio 5, 2008 by luisrey

Aunque mi primera intención es reunir información en castellano sobre la programación en Mac OSX no puedo deja de lado lo mejor en otros idiomas, y en este caso es excelente.

En el Bloc d’Apple en català hay información y noticias sobre Apple en catalán. Pero en este caso lo interesante es que están desarrollando varios cursos sobre programación en Mac OSX. De momento van tres cursos (Objective-C, Curs d’eines y Cocoa). Cada curso consta de varios screencast, las correspondientes entradas en el blog y un foro de discusión.

De nuevo en marcha…

Julio 5, 2008 by luisrey

Después de más de dos meses de atasco voy a intentar recuperar de nuevo el ritmo de publicación. Me han pasado varias cosas desde marzo cuando podía publicar con regularidad. He renovado ordenador con nueva versión de XCode. He tenido que dedicar más tiempo a mi trabajo en el instituto. Y sobre todo me he quedado atascado en un problema, ¿Como detectar que se ha hecho clic sobre una linea dibujada en pantalla?

Pero al final he conseguido superar el problema y en el proceso he reunido un buen puñado de nuevas fuentes de información. Tengo la impresión que en estos meses las páginas dedicadas a la programación en Mac escritas en castellano se han multiplicado. Muchas de ellas con la vista puesta en el iPhone. En los próximos días tengo previstas varias notas con lo que he aprendido y varias de las página interesantes que he visitado.

Un saludo a todos,

Luis

Iconos en botones

Mayo 16, 2008 by luisrey

Una de las opciones para mejorar el aspecto de un programa es añadir botones con iconos. No necesariamente una barra de herramientas, sino un simple botón con una imagen.

Es muy sencillo:

  1. Crear la imagen
  2. Añadir la imagen al proyecto
  3. Crear el botón
  4. Añadir la imagen al botón

Respecto a crear la imagen no hay mucho que pueda explicar. Escoge tu programa de dibujo preferido y crea una imagen para el botón. Es muy recomendable que la imagen sea sencilla y refleje claramente la función del botón. Vamos esto es más fácil de decir que de hacer, desde luego lo mio no es el diseño gráfico. Eso si en lugar de hacer que el fondo sea de color es preferible que sea transparente para poder integrarse mejor en cualquier tipo de diseño.

flecha

Una vez tenemos la imagen hecha basta con arrastrarla desde la carpeta donde la hayamos guardado a la ventana de XCode (También se puede hacer con la opción de menú “Project | Add to project…“) :

Cuando añadimos la imagen nos pregunta si queremos copiarla dentro de la carpeta del proyecto (muy recomendable)

Luego debemos ir a Interface Builder (por ejemplo haciendo doble clic en MainMenu.nib) y en la ventana del programa añadir un botón.

Con el botón creado en el tamaño que nos interesa ya podemos añadir la imagen. Para ello en el Inspector (cmd+1) escogemos la imagen que habíamos añadido al proyecto.

Y ya tenemos el trabajo hecho. Destacar que cuando miramos la simulación de la ventana no se ve el icono que acabamos de añadir. Imagino que es un pequeño error que se corregirá en versiones posteriores de XCode.

Y aquí tenemos el programa con su botón en funcionamiento.

XCode 3

Abril 12, 2008 by luisrey

Rápido: ya estoy trabajando con XCode 3….

No tengo muchas intenciones de explicar cosas personales en este blog, pero si que debo alguna explicación a tanto tiempo sin añadir entradas. Cómo a todos hay veces que se acumulan cosas. En mi caso las vacaciones de Semana Santa han sido ….. estresantes. Luego he tenido mucho trabajo y me presento a unas oposiciones para catedrático. Y para acabar he renovado el ordenador. Vamos, que excusas tengo unas cuantas.

Con el nuevo ordenador ha venido Leopard y el nuevo Xcode. En Leopard nada especial, mucho diseño, algunas cosas muy útiles, pero en general nada extraordinario. Junto con Leopard también he tenido que instalar el nuevo XCode 3. Como sigo muy liado con mis obligaciones todavía no he podido trabajar en serio con el programa, pero la primera impresión es muy buena. Parece cada ve más sencillo, limpio y potente. Cambian varias cosas, alguna de ellas bastante importante como explica muy bien Alejandro Moreno en su blog Cocoa con leche: Instanciar clases en Interface Builder 3

Cómo de costumbre en castellano hay pocas cosa y el mejor resumen de los cambios lo he encontrado en un artículo de David Gohara para Mac Research: Xcode and Interface builder . A brief overview

Espero publicar próximamente más artículos y revisar los ya escritos para que funcionen correctamente en Leopard.

 

Macuarium

Marzo 12, 2008 by luisrey

Repasando los enlaces que he puesto acabo de ver que falta uno fundamental:  Macuarium.

Macuarium

Macuarium es una página dedicada a los Mac y a Apple. Las noticias y artículos que publica son interesantes y no se limita a publicar las noticias refritas de otros sitios de rumores.

Pero lo mejor de Macuarium no es la página, sino los foros. Quizá un poco pretenciosamente se hace llamar “comunidad“. Pero es de los pocos foros que conozco por Internet dónde se procura mantener el máximo respeto por todos los participantes. Se pueden ver preguntas de novatos a auténticas discusiones de un altísimo nivel técnico.

De entre los foros el que ahora me interesa compartir con vosotros es el foro de programación: Desarrollo. Allí se pueden hacer preguntas sobre cualquier asunto, desde la programación con Objective-C a cosas más especializadas como programas hechos con Filemaker.

Wikibooks: Cocoa

Marzo 4, 2008 by luisrey

WikibooksWikipedia extiende sus tentáculos en varias direcciones. Una de ellas son los wikilibros. Según su propia definición:

Este proyecto está integrado al proyecto wikimedia y tiene por objetivo poner a la disposición de cualquier persona libros de texto, manuales, tutoriales u otros textos pedagógicos de contenido libre y de acceso gratuito.

En castellano podemos encontrar un completísimo manual de LaTeX, entre otros. Y en inglés hay toda una categoría para la programación con Cocoa: Wikibooks, Category:Cocoa. Bueno, eso de toda una categoría es muy relativo. De momento sólo hay dos libros, uno sobre la programación con Cocoa en general (y que esta inacabado) y otro sobre la programación para principiantes: Programming Mac OS X with Cocoa for beginners.

Siguiendo al ratón

Febrero 24, 2008 by luisrey

Una de las necesidades básicas de cualquier programa es aumentar la interacción con el usuario. Es decir, que el usuario tenga una información de que esta pasando, que esta haciendo. En ocasiones es muy importante poder seguir los movimientos del ratón. Bien para poder informar de algún punto de la pantalla, bien para dibujar siguiendo al ratón u otras opciones.

Es evidente que seguir siempre y en todo al ratón significa una carga muy importante para cualquier ordenador. Por eso hay varias estrategias para evitar al máximo el seguimiento del ratón. En primer lugar el seguimiento no esta activado siempre, solamente cuando se activa expresamente. En este artículo explicaré como se hace. Pero también hay estrategias más interesantes. Pero en Cocoa también se evita seguir al ratón en todas las tareas, por ejemplo si solamente hace falta cambiar el símbolo del cursor al pasar sobre un objeto no hace falta el seguimiento.

Para seguir al ratón nos harán falta tres cosas:
1. Establecer que la vista con la que trabajamos sea responsable de la respuesta
2. Crear el área de seguimiento
3. Aceptar los eventos de seguimiento
4. Reescribir las funciones para gestionar los eventos del ratón

¡Atención! Este método sirve para Tiger (10.4.x) y para Leopard (10.5.x) pero en este último es un método desaconsejado y puede dejar de funcionar en versiones futuras. Más información en addTrackingArea:.

1. Responsable de la primera respuesta

Para seguir al ratón lo primero es crear una vista personalizada (ver ….) y convertir esta vista en receptora primaria de los distintos eventos del sistema. Para ello simplemente sobreescribir la función acceptsFirstResponder

- (BOOL)acceptsFirstResponder {
return YES;
}

2. Crear el área de seguimiento

El siguiente paso es definir un área de seguimiento. Esto se hace con el método creando un objeto del tipo NSTrackingRectTag y asignando el área de seguimiento con el mensaje addTrackingRect:, por ejemplo:

areaSeguimiento = [self addTrackingRect:[self visibleRect]
    owner: self
    userData: nil
    assumeInside: YES];

En el código anterior areaSeguimiento es un objeto del tipo NSTrackingRectTag que se ha inicializado anteriormente. Quien recibe el mensaje addTrackingRect: es la propia vista ( y no tenemos que programar nada, maravillas de la herencia Cocoa :) ). Como parámetros hay que enviar el objeto NSRect (rectángulo) dónde se va a hacer el seguimiento ([self visibleRect]). Quien se encarga de la gestión del seguimiento (owner:self), en este caso la propia vista, pero podría ser otro objeto. También los datos del evento para el usuario (userData: nil), en el ejemplo, nada, nil. Y cómo último parámetro si se asume que el ratón comienza estando dentro o fuera del área de seguimiento.

3. Aceptar los eventos de seguimiento

Pese a crear el área de seguimiento además hay que activarla. Para ello hay que enviar el mensaje SetAcceptsMouseMovedEvents:YES a la ventana (sí, a la ventana) dónde esta incluida la vista.

[[self window] setAcceptsMouseMovedEvents:YES];

4. Funciones de eventos

Una vez definida y activada el área hay que crear las funciones que gestionarán los eventos de ratón. En concreto tres: entrada y salida del ratón del área de seguimiento, y la función del movimiento

4.1. Entrada y salida del área

Para definir lo que hará cada vez que el ratón entra o sale del área de seguimiento, por ejemplo:

- (void)mouseEntered:(NSEvent *)evento{
    [[self window] setAcceptsMouseMovedEvents:YES];
}
- (void)mouseExited:(NSEvent *)evento{
    [[self window] setAcceptsMouseMovedEvents:NO];
}

En el ejemplo sólo lo más sencillo activar y desactivar el seguimiento del ratón cuando entra y sale de la ventana.

4.2. Movimiento del ratón

Y por fin a lo importante, que hacer con los movimientos del ratón. Hace falta sobreescribir la función mouseMoved: Por ejemplo

- (void)mouseMoved:(NSEvent *)evento{
    puntoActual = [self convertPoint:[evento locationInWindow] fromView:nil];
    [self setNeedsDisplay:YES];
}

Dibus y la interacción

En el caso de mi programa Dibus (en creación y que espero que sea maravilloso) añadir un área de seguimiento hace que ahora se vean las rectas mientras las estamos dibujando.

Más información

ADC: Cocoa Event-Handling Guide. Using Tracking-Area Object

Simson Garfinkel, Michael Mahoney, Building Cocoa Applications: A Step by Step Guide. Mayo 2002, O’Reilly, [http://www.oreilly.com/catalog/buildcocoa/]

Dibus

Febrero 18, 2008 by luisrey

Al final me he decidido, Ya tengo objetivo para los próximos meses: convertir Dibus en un sencillo programa de dibujo vectorial. Desde luego muy lejos de Freehand, Illustrator y familiares. También muy lejos de Inskcape (gratuito y muy completo). Pero todos estos programas tienen más potencial que el que yo estoy en posición de utilizar.

Mi objetivo es poder crear sencillos gráficos vectoriales como los esquemas que he ido poniendo en la web, pequeños dibujos, etc. Todo ello en un programa que tendrá que ser fácil de utilizar, rápido y comprensible. ¿Seré capaz de conseguirlo?

Cómo resulta que yo tengo muy poca experiencia en Cocoa y Objective-C tengo que aprender y dejar constancia de todo lo que aprendo. Y que mejor forma que todo eso también sirva a otros. Podreís verlo en directo en este bloc.

Espero en los próximos meses definir claramente que tendrá y que no tendrá el programa. De momento voy a crear una página para recoger la definición del programa y sus diferentes versiones.

Dibus, dibujo vectorial sencillo

El bloc d’en Cesc, Cocoa/Xcode 2

Febrero 8, 2008 by luisrey

Noveo

El bloc d’enCesc, Cocoa/Xcode 2, es un blog en catalán con información sobre diferentes aspectos de la programación (Cocoa, Flash, páginas web, etc). Quizá algo desenfocado y no especializado, pero el tutorial sobre cómo crear programas con XCode2 es muy bueno.