TsimpleGraph Ortogonal Polyline link

Please post bug reports, feature requests, or any question regarding the DELPHI AREA products here.

TsimpleGraph Ortogonal Polyline link

Postby sergisan » January 30th, 2006, 10:57 pm

I have implemented a simple Ortogonal polyline link class.

It is very simple and it is make for my needs, the link always starts from the

bottom center of the starting node and always ends at the top center of the

destination node. There is no colision detection (its up to the user to avoid it)

I need it to make some kind of flow chart.

I f some body is interested...just ask.


Sergi.
Attachments
screen2.JPG
screen2.JPG (52.55 KiB) Viewed 5049 times
sergisan
Active Member
Active Member
 
Posts: 20
Joined: October 19th, 2005, 8:30 pm

Postby elias » February 1st, 2006, 8:41 am

I'd like to have such link class in my SG; could you send me/show me the code??
elias
Senior Member
Senior Member
 
Posts: 90
Joined: November 8th, 2005, 12:09 pm
Location: Galicia, Spain

source

Postby sergisan » February 1st, 2006, 1:11 pm

Here is the code.

Thank's to Stefan.

Code: Select all
   { TOrtoLink }

  TOrtoLink = class(TGraphLink)
  private
        UltPunto  : integer; // cantida de puntos en uso del siguiente array
        Puntos: array [0..5] of TPoint; ///
  protected
        procedure DrawMarkers(Canvas: TCanvas); override;
        procedure DrawBody(Canvas: TCanvas); override;
        procedure CalculateEndPoints;override;
        function GetTextRegion: HRGN; virtual;
  public
        constructor Create(AOwner: TSimpleGraph); override;
        function ContainsPoint(X, Y: Integer): Boolean; override;
  end;

 
{TOrtoLink}
constructor TOrtoLink.Create(AOwner: TSimpleGraph);
begin
    inherited Create(AOwner);
    UltPunto    := 2;
    Text        := 'Orto';
    setKind(lkDirected);
end;

function TOrtoLink.ContainsPoint(X, Y: Integer): Boolean;
var
  Margin,i: Integer;
  R: TRect;
begin
  Result := False;
  if Showing and (FromNode <> nil) and (ToNode <> nil) then /////
  begin
    if (TextRegion <> 0) and PtInRegion(TextRegion, X, Y) then
      Result := True
    else
    begin
      Margin := Pen.Width + Owner.MarkerSize;
      if DistanceToLine(StartPt, EndPt, Point(X, Y)) <= Margin then
      begin
        Margin := Margin div 2;
        R := MakeRect(StartPt, EndPt);
        InflateRect(R, Margin, Margin);
        Result := PtInRect(R, Point(X, Y));
        exit;
      end;
      for i := 0 to UltPunto -1 do
      begin
          if DistanceToLine(Puntos[i], Puntos[i+1], Point(X, Y)) <= Margin then
          begin
            Margin := Margin div 2;
            R := MakeRect(Puntos[i], Puntos[i+1]);
            InflateRect(R, Margin, Margin);
            Result := PtInRect(R, Point(X, Y));
            exit;
          end;
      end;

    end;
  end;
end;

procedure TOrtoLink.DrawMarkers(Canvas: TCanvas);
var
    rect : Trect;
    i    : byte ;
begin
///
  if not Dragging and IsVisibleOn(Canvas) then
  begin
    Canvas.Brush.Color := Owner.MarkerColor;
    Canvas.Brush.Style := bsSolid;
    //Canvas.FillRect(MarkerRect(mtMoveStrartPt));
    //Canvas.FillRect(MarkerRect(mtMoveEndPt));
    if (FromNode <> nil) and (ToNode <> nil) then
    begin
        for  i := 0 to UltPunto do
        begin
            SetRect(Rect, Puntos[i].X, Puntos[i].Y, Puntos[i].X, Puntos[i].Y);
            InflateRect(Rect, Owner.MarkerSize, Owner.MarkerSize);
            Canvas.FillRect(rect);
        end;
    end;
  end;
end;

procedure TOrtoLink.DrawBody(Canvas: TCanvas);

  procedure DrawArrow(const Pt: TPoint; ArrowScale: Integer);
  var
    ArrowHeight: Integer;
    ArrowPts: array[1..3] of TPoint;
  begin
    if Owner.MarkerSize > Pen.Width then
      ArrowHeight := ArrowScale * Owner.MarkerSize
    else
      ArrowHeight := ArrowScale * Pen.Width;
    ArrowPts[1] := Pt;
    ArrowPts[2] := Point(pt.X - ArrowHeight div 2, pt.Y - ArrowHeight div 2);
    //ArrowPts[3] := Point(pt.X , pt.Y - ArrowHeight div 3);
    ArrowPts[3] := Point(pt.X + ArrowHeight div 2, pt.Y - ArrowHeight div 2);
    Canvas.Polygon(ArrowPts);
  end;

begin
    Canvas.Polyline(Puntos);
    if Kind <> lkUndirected then
    begin
      DrawArrow(Puntos[UltPunto], ArrowSize);
      if Kind = lkBidirected then
        DrawArrow(Puntos[0], -ArrowSize);
    end;
end;

procedure TOrtoLink.CalculateEndPoints;
    Var i,x1,y1,x2,y2: integer;
begin
  if (FromNode <> nil) and (ToNode <> nil) and (State = osNone) then
  begin

    x1 := FromNode.Center.X;
    y1 := FromNode.Center.Y;

    x2 := ToNode.Center.X;
    y2 := ToNode.Center.y;

    for i := 0 to 5 do Puntos[i] := Point(0,0);

    if y2 >y1 then  // el destino esta po debajo del origen
    begin
        if x2 <> x1 then  // no estan alineados
        begin
            Puntos[0] := Point(FromNode.Center.X, FromNode.Top + FromNode.Height);
            Puntos[1] := Point(Puntos[0].X , Puntos[0].y +10);
            Puntos[3] := Point(ToNode.Center.X, ToNode.Top);
            Puntos[4] := Puntos[3];
            Puntos[5] := Puntos[3];
            // cuidao que este se haga despuesd de pUntos[3] sino valdra 0
            Puntos[2] := Point(Puntos[3].X, Puntos[1].y);
            UltPunto  := 3;
            fStartPt := Puntos[1];
            fEndPt   := Puntos[2];
            fAngle := 0;
        end
        else// estan alineados
        begin
            Puntos[0] := Point(FromNode.Center.X, FromNode.Top + FromNode.Height);
            Puntos[1] := Point(ToNode.Center.X, ToNode.Top);
            Puntos[2] := Puntos[1];
            Puntos[3] := Puntos[1];
            Puntos[4] := Puntos[1];
            Puntos[5] := Puntos[1];
            // cuidao que este se haga despuesd de pUntos[3] sino valdra 0
            UltPunto  := 2;
            fStartPt := Puntos[0];
            fEndPt   := Puntos[1];
            fAngle   := pi / 2;
        end;
    end
    else //if y2 >y1 then
    begin  // el destino esta por encima del origen
        if x2 < x1 then
        begin
            Puntos[0] := Point(FromNode.Center.X, FromNode.Top + FromNode.Height);
            Puntos[1] := Point(Puntos[0].X , Puntos[0].y +10);
            Puntos[2] := Point(10+ FromNode.Center.X + FromNode.Width div 2 , Puntos[1].y);
            Puntos[3] := Point(Puntos[2].x,ToNode.Top -10);
            Puntos[4] := Point(ToNode.Center.X, ToNode.Top -10);
            Puntos[5] := Point(ToNode.Center.X, ToNode.Top );
            // cuidao que este se haga despuesd de pUntos[3] sino valdra 0
            UltPunto  := 5;
        end
        else
        begin
            Puntos[0] := Point(FromNode.Center.X, FromNode.Top + FromNode.Height);
            Puntos[1] := Point(Puntos[0].X , Puntos[0].y +10);
            Puntos[2] := Point( FromNode.Center.X - FromNode.Width div 2 -10 , Puntos[1].y);
            Puntos[3] := Point(Puntos[2].x,ToNode.Top -10);
            Puntos[4] := Point(ToNode.Center.X, ToNode.Top -10);
            Puntos[5] := Point(ToNode.Center.X, ToNode.Top );
            // cuidao que este se haga despuesd de pUntos[3] sino valdra 0
            UltPunto  := 5;
        end;
        fStartPt := Puntos[2];
        fEndPt   := Puntos[3];
    end;

    CalculateTextParameters(True, 0, 0);
  end;
end;


function TOrtoLink.GetTextRegion: HRGN;
const
  DrawTextFlags = DT_NOPREFIX or DT_END_ELLIPSIS or DT_EDITCONTROL or
                  DT_MODIFYSTRING or DT_CALCRECT;
var
  RgnPts: array[1..4] of TPoint;
  ArrowHeight: Integer;
  LineWidth: Integer;
  TextRect: TRect;
  TmpText: String;
begin
  Result := 0;
  TextToShow := '';
  if (Text <> '') and (FromNode <> nil) and (ToNode <> nil) then
  begin
    if Owner.MarkerSize > Pen.Width then
      ArrowHeight := 4 * Owner.MarkerSize
    else
      ArrowHeight := 4 * Pen.Width;
    LineWidth := Trunc(Sqrt(Sqr(StartPt.X - EndPt.X) + Sqr(StartPt.Y - EndPt.Y)));
    if LineWidth > 3 * ArrowHeight then
    begin
      Dec(LineWidth, 3 * ArrowHeight);
      SetRect(TextRect, 0, 0, LineWidth, 0);
      Owner.Canvas.Font := Font;
      TmpText := Trim(Text);
      SetLength(TmpText, Length(TmpText) + 4);
      Windows.DrawText(Owner.Canvas.Handle, PChar(TmpText), -1, TextRect,
        Owner.DrawTextBiDiModeFlags(DrawTextFlags));
      SetLength(TmpText, StrLen(PChar(TmpText)));
      TextToShow := TmpText;
      TextCenter.X := (StartPt.X + EndPt.X) div 2;
      TextCenter.Y := StartPt.Y;//(StartPt.Y + EndPt.Y) div 2;
      TextCenter := NextPointOfLine(Angle - Pi / 2, TextCenter, TextRect.Top);
      OffsetRect(TextRect, TextCenter.X - TextRect.Right div 2,
                         TextCenter.Y - TextRect.Bottom);
      RgnPts[1] := TextRect.TopLeft;
      RgnPts[2] := Point(TextRect.Right, TextRect.Top);
      RgnPts[3] := TextRect.BottomRight;
      RgnPts[4] := Point(TextRect.Left, TextRect.Bottom);
      if Abs(Angle) > Pi / 2 then
        RotatePoints(RgnPts, Angle - Pi, TextCenter)
      else
        RotatePoints(RgnPts, Angle, TextCenter);
      Result := CreatePolygonRgn(RgnPts, 4, ALTERNATE);
    end;
  end;
end;
sergisan
Active Member
Active Member
 
Posts: 20
Joined: October 19th, 2005, 8:30 pm

Postby elias » February 1st, 2006, 1:38 pm

Gracias; lo implementaré en cuanto pueda; creo que tardaré un buen rato en entender el código. :)

Thanks for code, I'll watch it carefully and I'll tell you.

I think I've read there are a written new Link class (anything like ¿bezier? link Class) or anything like this in the project ExtGraph; Does'nt it sounds interesting?
elias
Senior Member
Senior Member
 
Posts: 90
Joined: November 8th, 2005, 12:09 pm
Location: Galicia, Spain

Postby elias » February 2nd, 2006, 10:38 am

I already prooved it;
It works, although I find that I have to move the link by hooking a not end or start marker, but intermediate.

The problem I found with the class is that is not independent; this is:
-If I have my unit SimpleGraph.pas and implement OrtoLink, then All Right.
-If I have my unit SimpleGraph.pas like component self-content; and I have another unit: GraphObjects.pas (here is where I develop and prove new Links and Node classes), and I implement OrtoLink I have several errors (in number of 10) and I can not compile.
I think I'll try to mend this issue when I have bit time.

Just that; Buen trabajo!

PD: I was looking at sourceforge.net ExtGraph>files; but only find a old SG version. ¿What with Bezier Links? ¿Anybody knows?
elias
Senior Member
Senior Member
 
Posts: 90
Joined: November 8th, 2005, 12:09 pm
Location: Galicia, Spain

Postby Kambiz » February 3rd, 2006, 12:11 pm

Just to save any extra work for you guys, I should annonce here that I'm currently working on the new release of the component.

So far many new features are implemented, and adding break points to the links is under construction.

Cheers
Kambiz
User avatar
Kambiz
Administrator
Administrator
 
Posts: 2408
Joined: March 7th, 2003, 7:10 pm

Postby elias » February 3rd, 2006, 12:23 pm

:)
you never get tired hmm?
elias
Senior Member
Senior Member
 
Posts: 90
Joined: November 8th, 2005, 12:09 pm
Location: Galicia, Spain

Postby kokkoras » February 5th, 2006, 1:38 pm

I hope for a back-compatible release.
User avatar
kokkoras
Moderator
Moderator
 
Posts: 317
Joined: March 12th, 2005, 11:19 pm
Location: Thessaloniki, Greece

Postby Kambiz » February 5th, 2006, 4:54 pm

Imagine a limousine being fully backward compatible with its ancestor: cart.

I'm trying to keep it backward compatible. But for those of you who are using the modified version of SimpleGraph, there might be some problems. Adding breakpoints to the links needed some major changes, sorry.

Hopefully SimpleGraph doesn't have same costumers of limousine, otherwise breaking backward campatibility was a big issue. :)
Kambiz
User avatar
Kambiz
Administrator
Administrator
 
Posts: 2408
Joined: March 7th, 2003, 7:10 pm

Postby sergisan » February 6th, 2006, 7:22 am

Good News.

Kambiz, Than You.

Sergi.
sergisan
Active Member
Active Member
 
Posts: 20
Joined: October 19th, 2005, 8:30 pm

Postby elias » February 7th, 2006, 2:30 pm

I guess you will use link markers between lines of each link. Adding the posibility of multiple markers, I could derivate, for example: Arc-Links, Bezier-Links...
Would be great if this were posible...
elias
Senior Member
Senior Member
 
Posts: 90
Joined: November 8th, 2005, 12:09 pm
Location: Galicia, Spain

Postby kokkoras » February 7th, 2006, 2:51 pm

elias wrote: Arc-Links, Bezier-Links...
Would be great if this were posible...


Yeah! Like in M$-Visio... (not easy at all)
User avatar
kokkoras
Moderator
Moderator
 
Posts: 317
Joined: March 12th, 2005, 11:19 pm
Location: Thessaloniki, Greece

Postby Kambiz » February 7th, 2006, 3:49 pm

Just for your information, currently I'm working on:

  • Implememnted: Custom breakpoints for links.
  • Implemented: General options including Seletable, Linkable, and ShowCaption
  • Implemented: Link options including FixedStartPoint, FixedEndPoint, and FixedBreakPoints.
  • Implemented: Node options including Movable, Resizable, and ShowBackground
  • Implemented but needs some adjustments: Links not only can be between two nodes, but also can be between a link and a node, or even between two links.
  • Under Construction: Having line object, or in the other hand a link without need of any linked object.
  • Under Construction: Each object manages keyboard and mouse events by itself. In this case, a new drived object can easily have its own control points.
Backward campatibility breaks the ... :roll:
Kambiz
User avatar
Kambiz
Administrator
Administrator
 
Posts: 2408
Joined: March 7th, 2003, 7:10 pm

Postby elias » February 7th, 2006, 6:30 pm

Kambiz wrote:
  • Implemented but needs some adjustments: Links not only can be between two nodes, but also can be between a link and a node, or even between two links.

That's good, really; I was indeed going to implement this in my .pas!!
elias
Senior Member
Senior Member
 
Posts: 90
Joined: November 8th, 2005, 12:09 pm
Location: Galicia, Spain

Postby Kambiz » February 7th, 2006, 9:54 pm

elias wrote:
Kambiz wrote:
  • Implemented but needs some adjustments: Links not only can be between two nodes, but also can be between a link and a node, or even between two links.

That's good, really; I was indeed going to implement this in my .pas!!

I finished to complete this item. Now, I'm in the second step.

To satisfy your curiosity, here is a snapshot of SimpleGraph in this stage.
Attachments
NewSimpleGraph.gif
New Release of SimpleGraph - Under Cosntruction
NewSimpleGraph.gif (21.17 KiB) Viewed 4952 times
Kambiz
User avatar
Kambiz
Administrator
Administrator
 
Posts: 2408
Joined: March 7th, 2003, 7:10 pm

Next

Return to DELPHI AREA Products

Who is online

Users browsing this forum: No registered users and 1 guest

cron