Wednesday, 5 November 2008

Jugando con TCanvas: Conectando Objetos en Delphi (Parte III).

  • Conectando los componentes con una flecha:
Para que podamos dar sentido a nuestras conexiones, restaría crear una punta de flecha en la línea de conexión entre objetos. Para eso, tenemos que recuperar nuestros apuntes de álgebra y geometría. El esquema de la flecha vendría a ser el siguiente:


Y el algoritmo para crear esta flecha en un TImage, es el siguiente:




type
TPointEx = packed record
X: Extended;
Y: Extended;
end;

...

function PointEx(X, Y: Extended): TPointEx;
begin
Result.X := X;
Result.Y := Y;
end;

...

procedure DrawArrow(Canvas: TCanvas; POrigen, PDestino: TPoint; LongitudFlecha: integer; RellenarPunta: boolean; color: TColor);
var
Triangulo: array[0..2] of TPoint;
LongitudVector, LongitudVectorNormal: Double;
DifLinea, BaseTriangulo, VectorNormal: TPoint;
FlechaNormal, ZonaMedia: TPoint;
DifUnitariaLinea, DifUnitariaNormal: TPointEx;
begin
Canvas.Pen.Color := color;
Canvas.Brush.Style := bsSolid;

//Dibujamos la línea
Canvas.MoveTo(POrigen.x, POrigen.y);
Canvas.LineTo(PDestino.x, PDestino.y);

//Buscamos la diferencia de componentes y la longitud del vector
DifLinea := Point(
PDestino.x - POrigen.x,
PDestino.y - POrigen.y);
LongitudVector := sqrt(sqr(DifLinea.x) + sqr(DifLinea.y));

DifUnitariaLinea := PointEx(
DifLinea.x / LongitudVector,
DifLinea.y / LongitudVector);

//BaseTriangulo donde la flecha es perpendicular a la base del triangulo
BaseTriangulo := Point(
PDestino.x - round(LongitudFlecha * DifUnitariaLinea.x),
PDestino.y - round(LongitudFlecha * DifUnitariaLinea.y));

VectorNormal := Point(DifLinea.y, -DifLinea.x);

LongitudVectorNormal := sqrt(sqr(VectorNormal.x) + sqr(VectorNormal.y));

DifUnitariaNormal := PointEx(
VectorNormal.x / LongitudVectorNormal,
VectorNormal.y / LongitudVectorNormal);

FlechaNormal := Point(
ROUND(LongitudFlecha * DifUnitariaNormal.x),
ROUND(LongitudFlecha * DifUnitariaNormal.y));

Triangulo[0] := Point(PDestino.x, PDestino.y);
Triangulo[1] := Point(BaseTriangulo.x + FlechaNormal.x, BaseTriangulo.y + FlechaNormal.y);
Triangulo[2] := Point(BaseTriangulo.x - FlechaNormal.x, BaseTriangulo.y - FlechaNormal.y);

//Dibujamos el poligono
Canvas.Polygon(Triangulo);

//Llenamos el triangulo de un color
if RellenarPunta then
begin
ZonaMedia := Point(
(Triangulo[0].x + Triangulo[1].x + Triangulo[2].x) div 3,
(Triangulo[0].y + Triangulo[1].y + Triangulo[2].y) div 3);
Canvas.Brush.Color := color;
Canvas.FloodFill(ZonaMedia.x, ZonaMedia.y, color, fsBorder);
end
end
;




El resultado en nuestra aplicación es el siguiente:





Este ejemplo lo podeis encontrar aquí.

0 comments:

Post a Comment