Monday, 21 September 2009

Punto perteneciente a un segmento

Continuando con el diseño de mi aplicación Thundax Box Manager, hoy os muestro la resolución de un problema típico al trabajar con selección de líneas sobre un canvas. El problema reside en calcular si un punto pertenece a una recta o no. Hacerlo a mano es bastante fácil, el problema es hacerlo con el PC. Aquí podéis ver una imagen que representa el problema en cuestión:

Verificar la ecuación manualmente es sencillo, ya que si disponemos de la ecuación de la recta del tipo y = mx + b (forma simplificada), solo tenemos que reemplazar los parámetros "x" y "y" y comprobar que hay un equilibrio en el resultado de la ecuación.

Matemáticamente, tendríamos que calcular la ecuación, y luego probar los parámetros sobre ésta y comprobar el equilibrio. Pero además lo que tenemos que hacer, es añadir un pequeño offset para que la selección de la línea ocurra cuando el puntero del mouse esté bastante cerca de la línea y no tengamos que activar el punto concreto de la línea, que puede llegar a ser molesto (intentar apuntar a un pixel es complicado).

Pues bien, con unas cuantas funciones, podemos llevar a cabo ésta configuración para que la selección de las líneas de la aplicación sea cómoda y fácil.

Por la red podréis encontrar innumerables trozos de código que solucionan éste problema, y además en cualquier lenguaje: Delphi, Java, C++, etc. Simplemente debéis escoger el que os vaya más bien.

Aquí os dejo el que he utilizado yo, una implementación de Juliano Zabeo que nos permite las opciones indicadas anteriormente.


uses
Math;

function pointBelongToLine(const target : Tpoint; line: Tline): boolean;
const
offset = 4;
var
lineInclination : TlineInclination;
max, min, calc : integer;
inclination, interception : double;
begin
result := false;
LineProperties(line, inclination, interception, lineInclination);

case lineInclination of
Hoz:
begin
min := minintvalue([line.source.x, line.target.x]);
max := maxintvalue([line.source.x, line.target.x]);
if (target.x >= min) and (target.x <= max) then
begin
calc := round( inclination * target.x + interception );
if abs(calc - target.y) <= offset then
result := true
end
end;
Vrt:
begin
min := minintvalue([line.source.y, line.target.y]);
max := maxintvalue([line.source.y, line.target.y]);
if (target.y >= min) and (target.y <= max) then
begin
calc := round( inclination * target.y + interception );
if abs(calc - target.x) <= offset then
result := true
end
end;
end
end;


El resultado lo podéis ver en la última versión de ThundaxBoxManager v1.0.0 build 116.exe:

  • Enlaces de interés:
Gráficos con Delphi.


0 comments:

Post a Comment