Thursday, 17 September 2009

Mejorando el diseño de una flecha (Parte I)

En éste artículo os mostraré un nuevo diseño de punta de flecha bastante mejorada de su antecesora: Drawing an Arrow. Últimamente he notado que el diseño que hice de ésta flecha no se acaba de ver bien cuando realizamos ciertas rotaciones y no me acaba de convencer. Así que he empezado a buscar nuevos diseños y por ejemplo Microsoft Office Word nos ofrece unos diseños de flecha bastante diferentes con la punta típica, otra más estilizada, un circulo, un rombo, etc. En éste caso me centraré en la punta de flecha más estilizada como en la que aparece en la imagen superior. Si observamos la siguiente imagen podremos ver las 2 flechas mas distintivas del Word:

Ahora, si os fijáis en mi aplicación, veréis que las flechas no se ven tan bien:

Por lo tanto, voy a intentar reemplazar la punta de flecha típica: , por una mas estilizada: . Por lo tanto me centraré en los cálculos que hay que hacer para poder dibujar ésta nueva flecha mas estilizada. En mi anterior post os mostré como se realizaba el cálculo para la punta de flecha típica:

Ahora el reto es dibujar una flecha mas estilizada de 4 puntos:

Si ampliamos la imagen podemos ver los cálculos que tenemos que realizar para poder calcular ésta nueva flecha:

Por defecto he dejado unos parámetros fijos para poder realizar el cálculo más rápido, aunque en la aplicación podremos llegar a personalizar éstos ángulos y longitudes a nuestro gusto. Aquí el tema está en construir ésta punta de flecha de 4 puntos igual que la de 3 puntos utilizando un polígono. De ésta manera la aplicación tendrá control sobre éste dibujo geométrico y será capaz de pintarlo interiormente y poner también el color que queramos:

En mi caso, el ángulo de inclinación de la flecha ya comenté como se calculaba en un post anterior utilizando el arcotangente entre el punto final y el inicial. Por defecto la inclinación hacia los puntos 2 y 4 es de 20º o sea pi/9 partes. La distancia entre los puntos 1 y 2 y 1 y 4 por defecto es de 20 píxels. El punto 3 está a 2/3 partes del punto 1, por lo tanto la generación de los puntos es la siguiente:
P1 := (Px, Py);
P2 := (Px, Py) + Move(-20 pixels) + Rotate(-pi/9);
P4 := (Px, Py) + Move(-20 pixels) + Rotate(+pi/9);
P3 := (Px, Py) + Move(-2/3 (Px,Py));
Mas o menos seria algo parecido a lo descrito anteriormente. Lo que tenemos que recordar es que en todo momento los datos son variables y podemos desplazar la flecha donde queramos, por lo tanto tenemos que tener en cuenta que éste recálculo tiene que ser lo mas rápido posible para que no se note el repintado.

Si analizamos el siguiente código veremos como se realizan los cálculos especificados:


uses
Math;

procedure DrawArrow(Canvas : TCanvas; Source, Target : TPoint; ArrowHeight : Integer);
function CalcPoint(p: TPoint; Angle: double; Distance: Integer): TPoint;
var
X, Y, M: Double;
begin
if Abs(Angle) <> (Pi / 2) then
begin
if Abs(Angle) < (Pi / 2) then
Distance := -Distance;
X := p.X + Distance / Sqrt(1 + Sqr(Tan(Angle)));
Y := p.Y + Tan(Angle) * (X - p.X);
Result := Point(Round(X), Round(Y));
end
else
begin
if Angle > 0 then
Distance := -Distance;
Result := Point(p.X, p.Y + Distance);
end;
end;
var
Angle : double;
PArrow: array[1..4] of TPoint;
begin
Canvas.MoveTo(Source.x, Source.y);
Canvas.LineTo(Target.x, target.y);
Angle := ArcTan2((Target.y - Source.y), (Target.x - Source.x));
PArrow[1] := Target;
PArrow[2] := CalcPoint(Target, Angle + Pi / 9, , ArrowHeight);
PArrow[3] := CalcPoint(Target, Angle, 2* ArrowHeight div 3);
PArrow[4] := CalcPoint(Target, Angle - Pi / 9, ArrowHeight);
Canvas.Polygon(PArrow);
end;


A partir de ahí, podemos ver el resultado en una pequeña aplicación de prueba:

Ahora solo falta añadir éstos cambios a la aplicación para que refleje ésta nueva flecha, mas estilizada y mas optimizada (en cálculos):

Podéis descargar la última versión estable de la aplicación desde aquí: ThundaxBoxManager v1.0.0 build 72.exe.

  • Enlaces de interés:
Funciones matemáticas con Delphi.

0 comments:

Post a Comment