Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quellcode-Bibliothek

© Kompilation durch diese Firma

[Weder Korrektheit noch Funktionsfähigkeit der Software werden zugesichert.]

Datei: k5sdb   Sprache: Delphi

unit Graphs;
//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
interface
uses
  //----------------------------------------------------------------------------
  //local
  //----------------------------------------------------------------------------
  OwnUtils,GenDefs,Utilities,OptionClass,language,
  //----------------------------------------------------------------------------
  //global
  //----------------------------------------------------------------------------
  Types,Graphics,Printers,ExtCtrls;
//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
type
  TGraphShape=(shRectangle,shRoundRectAngle,shElipse,shCircle,shRhombus,
    shSquare,shHuman,shDatabase,shMonitor,shBar);
  //----------------------------------------------------------------------------
  TArcOrientation=(aoSouthWest,aoSouthEast,aoNorthEast,aoNorthWest);
  //----------------------------------------------------------------------------
  PGraphVertice=^TGraphVertice;
  TGraphVertice= record
    Tree:integer;
    Target:boolean;
    Shape:TGraphShape;
    Position:TPoint;
    NodeWeight:integer;
    StartNode:boolean;
    FinalNode:boolean;
    CircleNode:boolean;
    DecisionNode:integer;
    Visited:boolean;
  end;
  //----------------------------------------------------------------------------
  TGraphEdge= record
    Side: array [1..2] of integer;
    Labeled:JStringKeyMax;
    MultipleEdge:boolean;
    EdgePos:TPoint;
    EdgeFil:StringFilemax;
  end;
  //----------------------------------------------------------------------------
  PGraphMap=^TGraphMap;
  TGraphMap= record
    Nodes: array of integer;
    Types: array of NType;
    Map:PGraphMap;
    MaxWeight,SumWeight:integer;
    MaxLeft,MaxRight,MaxTop,MaxBottom:integer;
  end;
  //----------------------------------------------------------------------------
  TGraph= Class(TObject)
    Vertices: array of TGraphVertice;
    Edges: array of TGraphEdge;
    Map:PGraphMap;
    CStream:PAnsiChar;
    Bezeichnung:JStringKeyMax;
    Beznr:integer;
    Verticecount,EdgeCount:integer;
    LastMarked:integer;//for marking
    MaxWeight,SumWeight:integer;
    Width,Height:integer;//virtual size
    VWidth,VHeight:integer;//virtual size
    VTop,VLeft:integer;//virtual size
    Content:PLongTexts;//Pointer to Tree
    B:TBitmap;
    Im,Imclear:TImage;
    diameter:variant;//dia of Node
    Sidelength:variant;//sidelength of square
    //fontsize:variant;//
    XBorder:integer;//border horizontal
    YBorder:integer;//border vertical
    Selected:integer;
    MaxLeft,MaxRight,MaxTop,MaxBottom:integer;
    Hint:JString;
    Hintpos:TPoint;
    LastSim:Tcolor;
    PI:real;
    //
    Linethickness:integer;
    //FontColor,BackgroundColor:Tcolor;
    //FontName:JString;
    //FontStyle:TFontStyles;
    //
    constructor Create(FontSiz,Lineth:integer;FontCol,BackgroundCol:Tcolor;
      FontNam:JString;FontStyl:TFontStyles;nr:integer;Txt:JString);
    destructor Destroy;override;
    procedure ImproveGraph();
    procedure SortGraph();
    procedure ScaleGraph();
    function GraphOrientation():TPrinterOrientation;
    function crossing(var S:TPoint;P1,P2,Q1,Q2:TPoint):boolean;
    function Maps(i:integer):PGraphVertice;
    function GraphCirclesCompress():boolean;
    function GraphWeightsCompress():boolean;
    function CollapsNode(var GM:PGraphMap;other:integer):boolean;
    function GraphStubShow(Tm:integer):boolean;
    procedure GraphWeights(OM:PGraphMap);
    procedure GraphExpand();
    procedure GraphCircles(n:integer);
    function AddVertex(n:integer):integer;
    procedure AddEdge(S:JString);
    function FindNode(n:integer):integer;
    procedure DeleteNode(n:integer);
    function PointCoordinates(n:integer):TPoint;
    function GetNodeTyp(S:JString;var ini:integer):NType;
    function getgraph(var TVL:LongTexts):boolean;
    procedure DrawGraph();
    procedure PCo(r:TRect;n:integer;O:boolean);
    procedure DetermineGraphSize();
    procedure Edge(O,G:TPoint;T:JString;multiple:boolean);
    procedure Vertex(Typ:NType;P:TPoint;T:JString;Mark:boolean;
      ou,pebbles:integer);
    procedure Grid(P:TPoint;DrawGrid:boolean);
    procedure Recreate(var Img:TImage;var B:TBitmap);
    procedure LabelEdge(O,G:TPoint;T:JString);
    procedure Arrowend(var B:TBitmap;P:TPoint;A:real;L:integer);
    procedure DrawConnectArc(O,G:TPoint;angle:variant);
    procedure DrawConnectLine(O,G:TPoint;angle:variant);
    procedure DrawConnectParallelLine(O,G:TPoint;angle:variant);
    procedure DrawConnectCircle(P:TPoint);
    procedure DrawArc(const Canvas:TCanvas;const color:Tcolor;
      const orientation:TArcOrientation;const x1,y1,x2,y2:integer;
      const BoundRect:TRect);
    procedure Arrowstart(var B:TBitmap;P:TPoint;A:real;L:integer);
    function FindGraphNode(Im:TImage;P:TPoint):integer;
    procedure GraphPositbyText(TF:JString;var Img:TImage);
    procedure GraphPositbyNode(Tm:integer;var Img:TImage);
    procedure GraphSimulate();
    procedure GraphSimulateRepeated();
    procedure GraphTraverse(n:integer);
    procedure ReDraw();
  end;
  //----------------------------------------------------------
  //
  //----------------------------------------------------------
implementation
uses
  Messages,SysUtils,Variants,Classes,Controls,Forms,Dialogs,
  StdCtrls,jpeg,Menus,ToolWin,Buttons,Math,StrUtils,
  ImgList,Chart,CheckLst,Clipbrd,ComCtrls,DateUtils;
//----------------------------------------------------------
//
//----------------------------------------------------------
constructor TGraph.Create(FontSiz,Lineth:integer;FontCol,BackgroundCol:Tcolor;
  FontNam:JString;FontStyl:TFontStyles;nr:integer;Txt:JString);
begin
  inherited Create();
  //fontsize:=FontSiz;
  Linethickness:=Lineth;
  //FontColor:=FontCol;
  //BackgroundColor:=BackgroundCol;
  //FontName:=FontNam;
  //FontStyle:=FontStyl;
  PI:=2*arcsin(1);
  BezNr:=Nr;
  setl(Bezeichnung,Txt);
end;
//----------------------------------------------------------
//
//----------------------------------------------------------
destructor TGraph.Destroy;
var P,Q:PGraphMap;
begin
  P:=Map;
  while (P<>nildo begin
    Q:=P;
    P:=P.Map;
    Dispose(Q);
  end;
  inherited Free;
end;
//----------------------------------------------------------
//
//----------------------------------------------------------
function TGraph.Maps(i:integer):PGraphVertice;
var
  M:PGraphMap;
begin
  if Map<>nil then begin
    M:=Map;
    while (M.Map<>nildo
      M:=M.Map;
  end
  else begin
    M:=nil;
  end;
  if M<>nil then
    Maps:=@Vertices[M.Nodes[i]]
  else
    Maps:=@Vertices[i];
end;
//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
procedure TGraph.ImproveGraph();
begin
  SortGraph();
end;
//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
function TGraph.GraphOrientation():TPrinterOrientation;
var
  Orient:TPrinterOrientation;
  GM:PGraphMap;
  mr,ml,mt,mb:integer;
begin
  ScaleGraph();
  GM:=Map;
  if GM=nil then begin
    ml:=MaxLeft;
    mr:=MaxRight;
    mt:=MaxTop;
    mb:=MaxBottom;
  end
  else begin
    while GM.Map<>nil do
      GM:=GM.Map;
    ml:=GM.MaxLeft;
    mr:=GM.MaxRight;
    mt:=GM.MaxTop;
    mb:=GM.MaxBottom;
  end;
  if abs(mr-ml)>abs(mb-mt) then
    Orient:=poLandscape
  else
    Orient:=poPortrait;
  GraphOrientation:=Orient;
end;
//------------------------------------------------------------------
//--
//On mouse down in Graph                                       --
//--
//------------------------------------------------------------------
function TGraph.FindGraphNode(Im:TImage;P:TPoint):integer;
var
  Tm,i,dc,dsm:integer;
  CP:TPoint;
begin
  Tm:=-1;
  dsm:=8000*8000;
  for i:=1 to Verticecount do begin //search for min x**2+y**2
    CP:=Maps(i).Position;
    dc:=sqr(P.X-CP.X)+sqr(P.Y-CP.Y);
    if (dc<dsm) then begin
      dsm:=dc;
      Tm:=i;
    end;
  end;
  //if dsm>Sidelength*G.Sidelength then
  //tm:=-1;
  FindGraphNode:=Tm
end;
//------------------------------------------------------------------
//--
//scale width and height of graph                              --
//--
//------------------------------------------------------------------
procedure TGraph.ScaleGraph();
var
  i:integer;
  GM:PGraphMap;
begin
  GM:=Map;
  if GM<>nil then begin
    While GM.Map<>nil do
      GM:=GM.Map;
    GM.MaxLeft:=2000;
    GM.MaxRight:=0;
    GM.MaxTop:=2000;
    GM.MaxBottom:=0;
    for i:=1 to Verticecount do begin //get coordinates of nodes
      If Maps(i).Position.X<MaxLeft then
        MaxLeft:=Maps(i).Position.X;
      If Maps(i).Position.X>MaxRight then
        MaxRight:=Maps(i).Position.X;
      If Maps(i).Position.Y<MaxTop then
        MaxTop:=Maps(i).Position.Y;
      If Maps(i).Position.Y>MaxBottom then
        MaxBottom:=Maps(i).Position.Y;
    end;
  end
  else begin
    MaxLeft:=8000;
    MaxRight:=-1;
    MaxTop:=8000;
    MaxBottom:=-1;
    for i:=1 to Verticecount do begin //get coordinates of nodes
      If Vertices[i].Position.X<MaxLeft then
        MaxLeft:=Vertices[i].Position.X;
      If Vertices[i].Position.X>MaxRight then
        MaxRight:=Vertices[i].Position.X;
      If Vertices[i].Position.Y<MaxTop then
        MaxTop:=Vertices[i].Position.Y;
      If Vertices[i].Position.Y>MaxBottom then
        MaxBottom:=Vertices[i].Position.Y;
    end;
  end;
end;
//------------------------------------------------------------------
//--
//sort graph by Position                                       --
//--
//------------------------------------------------------------------
procedure TGraph.SortGraph();
var
  i,j,k,pb,pe:integer;
  P:TPoint;
  function nodeisgreater(P1:TPoint;w1:integer;P2:TPoint;w2:integer):boolean;
  var
    ig:boolean;
    rd1,rd2,gw,gh:integer;
  begin
    gw:=max(Width,VWidth);
    gh:=max(Height,VHeight);
    with P1 do
      rd1:=abs(min(min(X,gw-X),min(Y,gh-Y)));
    with P2 do
      rd2:=abs(min(min(X,gw-X),min(Y,gh-Y)));
    ig:=(rd1>rd2)and(w1<=w2);
    nodeisgreater:=ig
  end;
  procedure exchange;
  begin
    P:=Maps(pb).Position;
    Maps(pb).Position:=Maps(pe).Position;
    Maps(pe).Position:=P;
  end;
begin
  for i:=1 to EdgeCount do begin //sort Nodes by Weight
    for j:=i+1 to EdgeCount do begin //sort Nodes by Weight
      for k:=1 to 2 do begin
        pb:=Edges[i].Side[k];
        pe:=Edges[j].Side[k];
        if nodeisgreater(Maps(pe).Position,Maps(pe).NodeWeight,
          Maps(pb).Position,Maps(pb).NodeWeight) then
          exchange
      end;
    end;
  end;
end;
//------------------------------------------------------------------
//--
//find circles in graph                                        --
//--
//------------------------------------------------------------------
procedure TGraph.GraphCircles(n:integer);
var
  i,j,newlength:integer;
  recurrent:boolean;
begin
  if VerticeStp>=Length(VerticeStack) then begin
    newlength:=Floor(Length(VerticeStack)*3/2);
    if VerticeStp>5 then
      errorn(92,'Setze neue Länge VerticeStack');
    SetLength(VerticeStack,newlength);
  end;
  VerticeStp:=VerticeStp+1;
  VerticeStack[VerticeStp]:=n;
  for j:=1 to EdgeCount do
    if Edges[j].Side[1]=n then begin
      recurrent:=false;
      for i:=1 to VerticeStp do
        if VerticeStack[i]=Edges[j].Side[2] then
          recurrent:=true;
      if not recurrent then
        GraphCircles(Edges[j].Side[2])
      else
        Maps(n).CircleNode:=true;
    end;
  VerticeStp:=VerticeStp-1
end;
//------------------------------------------------------------------
//--
//does an edge cros another adge?                              --
//--
//------------------------------------------------------------------
function TGraph.crossing(var S:TPoint;P1,P2,Q1,Q2:TPoint):boolean;
var
  waage1,waage2,senke1,senke2:boolean;
  tana1,tana2,alpha1,alpha2,d1,d2:real;
begin
  S.X:=0;
  S.Y:=0;
  waage1:=false;
  waage2:=false;
  senke1:=false;
  senke2:=false;
  alpha1:=0;
  alpha2:=0;
  d1:=0;
  d2:=0;
  crossing:=false;
  if (P2.X-P1.X<>0)and(P2.Y-P1.Y<>0) then begin
    //P1.Y  = alpha1*P1.X+d1
    //-> d1 = P1.Y - alpha*P1.X
    tana1:=(P2.Y-P1.Y)/(P2.X-P1.X);
    alpha1:=arctan(tana1);
    d1:=P1.Y-alpha1*P1.X;
    //P1.Y.=alpha1*P1.x+d1
  end
  else begin
    //ist waagerecht oder senkrecht
    if (P2.X-P1.X=0) then
      waage1:=true;
    if (P2.Y-P1.Y=0) then
      senke1:=true;
  end;
  if (Q2.X-Q1.X<>0)and(Q2.Y-Q1.Y<>0) then begin
    tana2:=(Q2.Y-Q1.Y)/(Q2.X-Q1.X);
    alpha2:=arctan(tana2);
    d2:=Q1.Y-alpha2*Q1.X;
    //Q1.Y=alpha2*Q1.x+d2
  end
  else begin
    //ist waagerecht oder senkrecht
    if (Q2.X-Q1.X=0) then
      waage2:=true;
    if (Q2.Y-Q1.Y=0) then
      senke2:=true;
  end;
  if not(waage1 or waage2 or senke1 or senke2) then begin
    //alpha1*x+d1=alpha2*x+d2
    //-> x(alpha1-alpha2)=d2-d1
    //-> x=(d2-d1)/(alpha1-alpha2)
    if abs(alpha1)<>abs(alpha2) then begin
      S.X:=Floor((d2-d1)/(alpha1-alpha2));
      S.Y:=Floor(alpha1*S.X+d1);
      crossing:=true;
    end
    else if d1=d2 then begin
      S.X:=P1.X;
      S.Y:=Floor(alpha1*S.X+d1);
      crossing:=true;
    end;
  end
  else if not senke1 and not senke2 and not waage1 and waage2 then begin
    S.X:=Q1.X;
    S.Y:=Floor(alpha1*S.X+d1);
    crossing:=true;
  end
  else if not senke1 and not senke2 and waage1 and not waage2 then begin
    S.X:=P1.X;
    S.Y:=Floor(alpha2*S.X+d2);
    crossing:=true;
  end
  else if not senke1 and not senke2 and waage1 and waage2 then begin
    S.X:=P1.X;
    S.Y:=P2.X;
    crossing:=P1.X=Q1.X;
  end
  else if not senke1 and senke2 and not waage1 and not waage2 then begin
    S.Y:=Q1.Y;
    S.X:=Floor((S.Y-d1)/alpha1);
    crossing:=true;
  end
  else if not senke1 and senke2 and not waage1 and waage2 then begin
    //impossible
  end
  else if not senke1 and senke2 and waage1 and not waage2 then begin
    S.X:=Q1.X;
    S.Y:=P1.Y;
    crossing:=true;
  end
  else if not senke1 and senke2 and waage1 and waage2 then begin
    //impossible
  end
  else if senke1 and not senke2 and not waage1 and not waage2 then begin
    S.Y:=P1.Y;
    S.X:=Floor((S.Y-d2)/alpha2);
    crossing:=true;
  end
  else if senke1 and not senke2 and not waage1 and waage2 then begin
    S.X:=Q1.X;
    S.Y:=P1.Y;
    crossing:=true;
  end
  else if senke1 and not senke2 and waage1 and not waage2 then begin
    //impossible
  end
  else if senke1 and not senke2 and waage1 and waage2 then begin
    //impossible
  end
  else if senke1 and senke2 and not waage1 and not waage2 then begin
    if P1.Y=Q1.Y then begin
      S.X:=P1.X;
      S.Y:=P1.Y;
      crossing:=true;
    end
  end
  else if senke1 and senke2 and not waage1 and waage2 then begin
    //impossible
  end
  else if senke1 and senke2 and waage1 and not waage2 then begin
    //impossible
  end
  else if senke1 and senke2 and waage1 and waage2 then begin
    //impossible
  end;
end;
//------------------------------------------------------------------
//--
//compress circles of graph                                    --
//--
//------------------------------------------------------------------
function TGraph.GraphCirclesCompress():boolean;
var
  node,i,left,right:integer;
  GM,OM:PGraphMap;
  ret:boolean;
  procedure Single(this:integer);
  var
    vert,i,newlength:integer;
    recptr,nod,newnod:integer;
  begin
    if VerticeStp>=Length(VerticeStack) then begin
      newlength:=Floor(Length(VerticeStack)*3/2);
      if VerticeStp>5 then
        errorn(93,'Setze neue Länge VerticeStack');
      SetLength(VerticeStack,newlength);
    end;
    VerticeStp:=VerticeStp+1;
    VerticeStack[VerticeStp]:=this;
    for vert:=1 to EdgeCount do begin
      left:=Edges[vert].Side[1];
      right:=Edges[vert].Side[2];
      if (left=this)and(left<>right) then begin
        recptr:=0;
        for i:=1 to VerticeStp-1 do
          if VerticeStack[i]=Edges[vert].Side[2] then
            recptr:=i;
        if recptr=0 then begin
          Single(right)
        end
        else begin
          ret:=true;
          nod:=VerticeStack[recptr];//create a new mapping
          newnod:=nod;
          for i:=recptr to VerticeStp do begin
            nod:=VerticeStack[i];
            GM.Nodes[nod]:=newnod;
            GM.Types[nod]:=loopitem;
          end;
        end;
      end;
    end;
    VerticeStp:=VerticeStp-1;
  end;
begin
  ret:=false;
  SetLength(VerticeStack,max(3,2*Verticecount));
  VerticeStp:=0;
  if Map<>nil then begin
    GM:=Map;
    while (GM.Map<>nildo
      GM:=GM.Map;
    new(GM.Map);
    OM:=GM;
    GM:=GM.Map;
  end
  else begin
    new(Map);
    OM:=nil;
    GM:=Map;
  end;
  SetLength(GM.Nodes,max(3,2*Verticecount));
  SetLength(GM.Types,max(3,2*Verticecount));
  GM.Map:=nil;
  for i:=1 to Verticecount do begin
    GM.Nodes[i]:=i;
    GM.Types[i]:=noitem;
  end;
  //noch komprimierbar?
  if (OM=nil)and(MaxWeight>2)or(OM<>nil)and(OM.MaxWeight>2) then begin
    for node:=1 to Verticecount do
      if Vertices[node].StartNode then
        Single(node);
    if ret then begin
      //Gewichte neu berechnen
      GM.MaxWeight:=0;
      GM.SumWeight:=0;
      for i:=1 to Verticecount do
        Vertices[i].NodeWeight:=0;
      for i:=1 to EdgeCount do begin
        left:=Edges[i].Side[1];
        right:=Edges[i].Side[2];
        Vertices[left].NodeWeight:=Vertices[left].NodeWeight+1;
        Vertices[right].NodeWeight:=Vertices[right].NodeWeight+1;
        GM.SumWeight:=GM.SumWeight+2;
        GM.MaxWeight:=max(GM.MaxWeight,Maps(left).NodeWeight);
        GM.MaxWeight:=max(GM.MaxWeight,Maps(right).NodeWeight);
      end;
    end
    else if OM<>nil then begin
      dispose(OM.Map);
      OM.Map:=nil;
    end
    else begin
      dispose(Map);
      Map:=nil;
    end;
  end;
  GraphCirclesCompress:=ret;
end;
//------------------------------------------------------------------
//--
//compress weights                                             --
//--
//------------------------------------------------------------------
function TGraph.GraphWeightsCompress():boolean;
var
  node,i,left,right:integer;
  reducibleweight:integer;
  GM,OM:PGraphMap;
  ret:boolean;
  procedure Single(this:integer);
  var
    vert,i,newlength:integer;
    nod,newnod:integer;
  begin
    if (Vertices[this].NodeWeight>=reducibleweight)and(GM.Nodes[this]=this)
      then begin
      VerticeStp:=1;
      VerticeStack[VerticeStp]:=this;
      for vert:=1 to EdgeCount do begin
        left:=Edges[vert].Side[1];
        right:=Edges[vert].Side[2];
        if ((right=this)or(left=this))and(left<>right) then begin
          if VerticeStp>=Length(VerticeStack) then begin
            newlength:=Floor(Length(VerticeStack)*3/2);
            if VerticeStp>5 then
              errorn(94,'Setze neue Länge VerticeStack');
            SetLength(VerticeStack,newlength);
          end;
          if (left=this) then begin
            ret:=true;
            VerticeStp:=VerticeStp+1;
            VerticeStack[VerticeStp]:=Edges[vert].Side[2]
          end;
          if (right=this) then begin
            ret:=true;
            VerticeStp:=VerticeStp+1;
            VerticeStack[VerticeStp]:=Edges[vert].Side[1]
          end;
        end;
        newnod:=GM.Nodes[this];
        for i:=1 to VerticeStp do begin
          nod:=VerticeStack[i];
          GM.Nodes[nod]:=newnod;
          GM.Types[nod]:=subtreeitem;
        end;
      end;
    end;
  end;
begin
  ret:=false;
  SetLength(VerticeStack,max(3,2*Verticecount));
  if Map<>nil then begin
    GM:=Map;
    while (GM.Map<>nildo
      GM:=GM.Map;
    new(GM.Map);
    OM:=GM;
    GM:=GM.Map;
    reducibleweight:=OM.MaxWeight;
  end
  else begin
    new(Map);
    OM:=nil;
    GM:=Map;
    reducibleweight:=MaxWeight;
  end;
  SetLength(GM.Nodes,max(3,2*Verticecount));
  SetLength(GM.Types,max(3,2*Verticecount));
  GM.Map:=nil;
  for i:=1 to Verticecount do begin
    GM.Nodes[i]:=i;
    GM.Types[i]:=noitem;
  end;
  //noch komprimierbar?
  if (OM=nil)and(MaxWeight>2)or(OM<>nil)and(OM.MaxWeight>2) then begin
    for node:=1 to Verticecount do
      Single(node);
    if ret then begin
      //Gewichte neu berechnen
      GM.MaxWeight:=0;
      GM.SumWeight:=0;
      for i:=1 to Verticecount do
        Vertices[i].NodeWeight:=0;
      for i:=1 to EdgeCount do begin
        left:=Edges[i].Side[1];
        right:=Edges[i].Side[2];
        Maps(left).NodeWeight:=Maps(left).NodeWeight+1;
        Maps(right).NodeWeight:=Maps(right).NodeWeight+1;
        GM.SumWeight:=GM.SumWeight+2;
        GM.MaxWeight:=max(GM.MaxWeight,Maps(left).NodeWeight);
        GM.MaxWeight:=max(GM.MaxWeight,Maps(right).NodeWeight);
      end;
    end;
    if (OM<>nilthen
      if (OM.MaxWeight<=GM.MaxWeight) then //no gain ??
        ret:=false;
  end;
  if not ret then begin
    if OM<>nil then begin
      dispose(OM.Map);
      OM.Map:=nil;
    end
    else begin
      dispose(Map);
      Map:=nil;
    end;
  end;
  GraphWeightsCompress:=ret;
end;
//------------------------------------------------------------------
//--
//collapse node                                                --
//--
//------------------------------------------------------------------
function TGraph.CollapsNode(var GM:PGraphMap;other:integer):boolean;
var
  ove,ovr,ovl,i,newlength,newnod,nod:integer;
  ret:boolean;
begin
  VerticeStp:=0;
  ret:=false;
  for ove:=1 to EdgeCount do begin
    ovl:=Edges[ove].Side[1];
    ovr:=Edges[ove].Side[2];
    if ((ovl=other)or(ovr=other))and(ovl<>ovr) then begin
      if VerticeStp+2>=Length(VerticeStack) then begin
        newlength:=Floor(Length(VerticeStack)*3/2);
        if VerticeStp>5 then
          errorn(95,'Setze neue Länge VerticeStack');
        SetLength(VerticeStack,newlength);
      end;
      if (ovl=other) then begin
        VerticeStp:=VerticeStp+1;
        VerticeStack[VerticeStp]:=ovr;
        ret:=true;
      end;
      if (ovr=other) then begin
        VerticeStp:=VerticeStp+1;
        VerticeStack[VerticeStp]:=ovl;
        ret:=true;
      end;
    end;
  end;
  newnod:=GM.Nodes[other];
  GM.Types[other]:=noitem;
  for i:=1 to VerticeStp do begin
    if GM.Types[i]=noitem then begin
      nod:=VerticeStack[i];
      GM.Nodes[nod]:=newnod;
      GM.Types[nod]:=subtreeitem;
    end;
  end;
  CollapsNode:=ret;
end;
//------------------------------------------------------------------
//--
//show only stubs                                              --
//--
//------------------------------------------------------------------
function TGraph.GraphStubShow(Tm:integer):boolean;
var
  i,left,right:integer;
  GM,OM:PGraphMap;
  ret:boolean;
  procedure Single(this:integer);
  var
    vert,other,firstother:integer;
  begin
    firstother:=0;
    if (Vertices[this].NodeWeight>1) then begin
      for vert:=1 to EdgeCount do begin
        left:=Edges[vert].Side[1];
        right:=Edges[vert].Side[2];
        if (left=this)or(right=this) then begin
          other:=this;
          if (left=this) then
            other:=right;
          if (right=this) then
            other:=left;
          if other<>this then begin
            ret:=ret or CollapsNode(GM,other);
          end;
        end
        else begin //left<>this and right<> this
          if firstother=0 then
            firstother:=left;
          ret:=ret or CollapsNode(GM,left);
          ret:=ret or CollapsNode(GM,right);
        end;
      end;
    end;
  end;
begin
  ret:=false;
  SetLength(VerticeStack,max(3,2*Verticecount));
  if Map<>nil then begin
    GM:=Map;
    while (GM.Map<>nildo
      GM:=GM.Map;
    new(GM.Map);
    OM:=GM;
    GM:=GM.Map;
  end
  else begin
    new(Map);
    OM:=nil;
    GM:=Map;
  end;
  if (OM<>nil)and(Tm<=Verticecount)and(Tm>=1)and(OM.Types[Tm]<>noitem) then
    begin
    SetLength(GM.Nodes,max(3,2*Verticecount));
    SetLength(GM.Types,max(3,2*Verticecount));
    GM.Map:=nil;
    for i:=1 to Verticecount do begin //identity
      GM.Nodes[i]:=i;
      GM.Types[i]:=noitem;
    end;
    //noch komprimierbar?
    if (OM=nil)and(MaxWeight>2)or(OM<>nil)and(OM.MaxWeight>2) then begin
      if (OM<>nil)and(OM.Types[Tm]<>noitem) then
        Single(Tm);
      if ret then begin
        //Gewichte neu berechnen
        GM.MaxWeight:=0;
        GM.SumWeight:=0;
        for i:=1 to Verticecount do
          Vertices[i].NodeWeight:=0;
        for i:=1 to EdgeCount do begin
          left:=Edges[i].Side[1];
          right:=Edges[i].Side[2];
          Vertices[left].NodeWeight:=Vertices[left].NodeWeight+1;
          Vertices[right].NodeWeight:=Vertices[right].NodeWeight+1;
          GM.SumWeight:=GM.SumWeight+2;
          GM.MaxWeight:=max(GM.MaxWeight,Maps(left).NodeWeight);
          GM.MaxWeight:=max(GM.MaxWeight,Maps(right).NodeWeight);
        end;
      end
    end;
  end;
  if not ret then begin
    if OM<>nil then begin
      dispose(OM.Map);
      OM.Map:=nil;
    end
    else begin
      dispose(Map);
      Map:=nil;
    end;
  end;
  GraphStubShow:=ret;
end;
//------------------------------------------------------------------
//--
//compute weights of nodes/Edges                            --
//--
//------------------------------------------------------------------
procedure TGraph.GraphWeights(OM:PGraphMap);
var
  i,left,right:integer;
begin
  if OM<>nil then begin
    //Gewichte neu berechnen
    OM.MaxWeight:=0;
    OM.SumWeight:=0;
    for i:=1 to Verticecount do
      Vertices[i].NodeWeight:=0;
    for i:=1 to EdgeCount do begin
      left:=Edges[i].Side[1];
      right:=Edges[i].Side[2];
      Vertices[left].NodeWeight:=Vertices[left].NodeWeight+1;
      Vertices[right].NodeWeight:=Vertices[right].NodeWeight+1;
      OM.SumWeight:=OM.SumWeight+2;
      OM.MaxWeight:=max(OM.MaxWeight,Maps(left).NodeWeight);
      OM.MaxWeight:=max(OM.MaxWeight,Maps(right).NodeWeight);
    end;
  end
  else begin
    //Gewichte neu berechnen
    MaxWeight:=0;
    SumWeight:=0;
    for i:=1 to Verticecount do
      Vertices[i].NodeWeight:=0;
    for i:=1 to EdgeCount do begin
      left:=Edges[i].Side[1];
      right:=Edges[i].Side[2];
      Vertices[left].NodeWeight:=Vertices[left].NodeWeight+1;
      Vertices[right].NodeWeight:=Vertices[right].NodeWeight+1;
      SumWeight:=SumWeight+2;
      MaxWeight:=max(MaxWeight,Maps(left).NodeWeight);
      MaxWeight:=max(MaxWeight,Maps(right).NodeWeight);
    end;
  end;
end;
//------------------------------------------------------------------
//--
//expand graph                                                 --
//--
//------------------------------------------------------------------
procedure TGraph.GraphExpand();
var
  P,L:PGraphMap;
begin
  P:=Map;
  if P<>nil then begin
    L:=P;
    while P.Map<>nil do begin
      L:=P;
      P:=P.Map
    end;
    if L.Map<>nil then begin
      dispose(L.Map);
      L.Map:=nil;
      GraphWeights(L);
    end
    else begin
      dispose(L);
      Map:=nil;
      GraphWeights(nil);
    end;
  end
  else begin
    if Map<>nil then begin
      dispose(Map);
      Map:=nil;
      GraphWeights(nil);
    end;
  end;
end;
//------------------------------------------------------------------
//--
//find node or create new                                      --
//--
//------------------------------------------------------------------
function TGraph.FindNode(n:integer):integer;
var
  i,r,RN:integer;
  found:boolean;
begin
  r:=1;
  RN:=n-1;
  found:=false;
  if n=0 then
    errorn(96,'node not found:'+IntToStr(n));
  for i:=1 to Verticecount do
    if Vertices[i].Tree=RN then begin
      found:=true;
      r:=i
    end;
  if not found then
    r:=AddVertex(RN);
  FindNode:=r
end;
//------------------------------------------------------------------
//--
//create new node                                              --
//--
//------------------------------------------------------------------
function TGraph.AddVertex(n:integer):integer;
var
  newlength:integer;
begin
  if Verticecount+1>=Length(Vertices) then begin
    newlength:=Floor((Verticecount*3)div 2+2);
    if Verticecount>5 then
      errorn(97,'Setze neue Länge vertices');
    SetLength(Vertices,newlength);
  end;
  //catcher(Verticecount=11);
  Verticecount:=Verticecount+1;
  Vertices[Verticecount].Tree:=n;
  Vertices[Verticecount].Target:=false;
  Vertices[Verticecount].Shape:=shRectangle;
  Vertices[Verticecount].Position.X:=0;
  Vertices[Verticecount].Position.Y:=0;
  Vertices[Verticecount].StartNode:=true;
  Vertices[Verticecount].FinalNode:=true;
  Vertices[Verticecount].CircleNode:=false;
  Vertices[Verticecount].DecisionNode:=0;
  Vertices[Verticecount].Visited:=false;
  AddVertex:=Verticecount
end;
//------------------------------------------------------------------
//--
//delete node                                                  --
//--
//------------------------------------------------------------------
procedure TGraph.DeleteNode(n:integer);
var
  i:integer;
begin
  if n=0 then
    errorn(98,'Löschung falsch');
  for i:=n to Verticecount-1 do
    Vertices[i]:=Vertices[i+1];
  Verticecount:=Verticecount-1;
  for i:=1 to EdgeCount do begin
    if Edges[i].Side[1]>n then
      Edges[i].Side[1]:=Edges[i].Side[1]-1;
    if Edges[i].Side[2]>n then
      Edges[i].Side[2]:=Edges[i].Side[2]-1;
  end;
end;
//------------------------------------------------------------------
//--
//create vertex                                                --
//--
//------------------------------------------------------------------
procedure TGraph.AddEdge(S:JString);
var
  newlength:integer;
  Line,Col:integer;
  Fil:JString;
begin
  if EdgeCount>=Length(Edges) then begin
    newlength:=Floor(EdgeCount*3/2);
    if EdgeCount>5 then
      errorn(99,'Setze neue Länge Edges');
    SetLength(Edges,newlength);
  end;
  EdgeCount:=EdgeCount+1;
  Line:=StrToInt(getpar(S_Lin,S));
  Col:=StrToInt(getpar(S_col,S));
  Fil:=getpar(S_Fil,S);
  Edges[EdgeCount].EdgePos.X:=Line;
  Edges[EdgeCount].EdgePos.Y:=Col;
  setl(Edges[EdgeCount].EdgeFil,Fil);
  Edges[EdgeCount].MultipleEdge:=false;
  setl(Edges[EdgeCount].Labeled,getpar(S_Lab,S));
end;
//------------------------------------------------------------------
//--
//load Graph from Stream/String                                --
//--
//------------------------------------------------------------------
function TGraph.getgraph(var TVL:LongTexts):boolean;
var
  L,i1,i2,P,k,Org,Dest,FromNode,ToNode,ll:integer;
  S,sl,sr:JString;
  SLINT,SRINT:integer;
  Point:TPoint;
  r:TRect;
  function slen():integer;
  var
    i:integer;
  begin
  i:=0;
  repeat
    GetNextRec(CStream);
    i:=i+1;
  until (errorcount>0)or eofs;
  i:=i+1;
   result:=i
  end;
  function xpos(F:Char;S:JString):integer;
  var
    i,P,O:integer;
  begin
    i:=Length(S);
    P:=-1;
    O:=0;
    while i>0 do begin
      if MidStr(S,i,1)=F then begin
        P:=i;
        O:=O+1;
        if O=2 then
          i:=0
      end;
      i:=i-1
    end;
    xpos:=P;
  end;
begin
  Point.X:=0;
  Point.Y:=0;
  OpenStream(CStream);
  //count edges
  ll:=slen();
  //now process
  try
    OpenStream(CStream);
    Content:=@TVL;
    SetLength(Vertices,2*ll);
    SetLength(Edges,ll);
    EdgeCount:=0;
    Verticecount:=0;
    Width:=0;
    Height:=0;
    VWidth:=0;
    VHeight:=0;
    VTop:=0;
    VLeft:=0;
    Map:=nil;
    B:=nil;
    diameter:=0;
    Sidelength:=0;
    XBorder:=0;
    YBorder:=0;
    MaxLeft:=0;
    MaxRight:=0;
    MaxTop:=0;
    MaxBottom:=0;
    Selected:=0;
    repeat
      S:=GetNextRec(CStream);
      if (MidStr(S,1,Length(S_LVert))=S_LVert) then begin
        //recordc contains only edges
        //<Edge Lin=8 Col=19 Fil=0 Typ=data.charitem from=1 to=2 Lab=SPACE>10,9</Edge>'
        AddEdge(S);
        sl:=getattribute(S_Left,S);
        TryStrtoInt(sl,SLINT);
        Edges[EdgeCount].Side[1]:=SLINT;
        sr:=getattribute(S_Right,S);
        TryStrtoInt(SR,SRINT);
        Edges[EdgeCount].Side[2]:=SRINT;
        FromNode:=Edges[EdgeCount].Side[1];
        Org:=FindNode(FromNode);
        Edges[EdgeCount].Side[1]:=Org;
        Vertices[Org].DecisionNode:=Vertices[Org].DecisionNode+1;
        ToNode:=Edges[EdgeCount].Side[2];
        Dest:=FindNode(ToNode);
        Edges[EdgeCount].Side[2]:=Dest;
        Vertices[Dest].StartNode:=false;
        if (Org<>Dest) then
          Vertices[Org].FinalNode:=false;
        //find overlapping Edges
        for k:=1 to EdgeCount-1 do
          if (Edges[k].Side[1]=Edges[EdgeCount].Side[2])and
            (Edges[k].Side[2]=Edges[EdgeCount].Side[1]) then begin
            Edges[EdgeCount].MultipleEdge:=true;
            Edges[k].MultipleEdge:=true;
          end
      end
      until (errorcount>0)or eofs;
      except
        On E:Exception do begin
          errorn(6,'Block Fehler, '+E.Message);
        end
      end;
      //calculate weights
      MaxWeight:=0;
      SumWeight:=0;
      for L:=1 to Verticecount do
        Vertices[L].NodeWeight:=0;
      for L:=1 to EdgeCount do begin
        i1:=Edges[L].Side[1];
        i2:=Edges[L].Side[2];
        Vertices[i1].NodeWeight:=Vertices[i1].NodeWeight+1;
        Vertices[i2].NodeWeight:=Vertices[i2].NodeWeight+1;
        SumWeight:=SumWeight+2;
        MaxWeight:=max(MaxWeight,Vertices[i1].NodeWeight);
        MaxWeight:=max(MaxWeight,Vertices[i2].NodeWeight);
      end;
      getgraph:=true;
      //now find coordinates
      r.left:=0;//left;
      r.top:=0;//top;
      r.right:=Width;
      r.bottom:=Height;
      PCo(r,Verticecount,false);
    end;
    //------------------------------------------------------------------
    //--
    //draw Graph                                                   --
    //--
    //------------------------------------------------------------------
    procedure TGraph.DrawGraph();
    var
      i,co,pb,pe:integer;
      NodeTyp:NType;
      ini:integer;
      TX,Nodei:JString;
      fontfact:extended;
      Framei:boolean;
      GM:PGraphMap;
      function w():integer;
      begin
        w:=VLeft+(PointCoordinates(1).X-Sidelength div 2)*Width div VWidth
      end;
      function h():integer;
      begin
        h:=VTop+(PointCoordinates(1).Y-Sidelength div 2)*Height div VHeight
      end;
    begin
      fontfact:=VWidth/Width;
      if fontfact=0 then
        fontfact:=1;
      if (self.Width>10)and(self.Height>10) then begin
        if Verticecount>0 then begin
          DetermineGraphSize();
          with B.Canvas do begin
            font.Name:=opt.R.FontName;
            font.color:=opt.R.FontColor;
            font.Style:=opt.R.FontStyle;
            font.Size:=opt.R.FontSize;
            Pen.color:=opt.R.FontColor;
            font.Size:=round(fontfact*opt.R.FontSize);
            TextOut(w(),h(),Bezeichnung);
          end;
          //Txt:=' w='+inttostr(Width)+' h='+inttostr(Height);B.Canvas.TextOut(8,15,Txt);
          //Txt:=' vw='+inttostr(VWidth)+' vh='+inttostr(VHeight);B.Canvas.TextOut(8,30,Txt);
          if errorcount=0 then
            with self do begin
              for i:=1 to Verticecount do //get coordinates of nodes
                Maps(i).Position:=PointCoordinates(i);
              GM:=Map;
              if GM<>nil then
                while GM.Map<>nil do
                  GM:=GM.Map;
              ImproveGraph();
              for i:=1 to EdgeCount do
                if errorcount=0 then begin
                  pb:=Edges[i].Side[1];
                  pe:=Edges[i].Side[2];
                  Edge(Maps(pb).Position,Maps(pe).Position,Edges[i].Labeled,
                    Edges[i].MultipleEdge)
                end;
              if GM<>nil then begin
                GM.MaxLeft:=Width;
                GM.MaxRight:=0;
                GM.MaxTop:=Height;
                GM.MaxBottom:=0;
              end;
              for i:=1 to Verticecount do
                if (errorcount=0)and(Length(Content^.items)>0) then begin
                  catcher(i=11);
                  co:=Maps(i).Tree;
                  Nodei:='';
                  NodeTyp:=noitem;
                  Framei:=false;
                  if (co>=0)and(co<=Length(Content^.items)) then begin
                    TX:=Content^.items[co].Text;
                    Nodei:=Functor(TX);
                    NodeTyp:=GetNodeTyp(TX,ini);
                    Framei:=false;
                    if GM<>nil then begin
                      if GM.Types[i]<>noitem then begin
                        NodeTyp:=GM.Types[i];
                        Nodei:='#'+Nodei+'#';
                      end;
                    end
                  end
                  else if (errorcount=0) then begin
                    errorn(7,
                      'Zuordnung falsch: '+IntToStr(co)+' von '+IntToStr
                        (Length(Content^.items)));
                  end;
                  Vertex(NodeTyp,Maps(i).Position,Nodei,Framei,
                    Maps(i).DecisionNode,ini);
                  Grid(Maps(i).Position,Opt.r.DrawGrid);//draw dotted grid
                end;
            end;
          Recreate(Im,B);
          Recreate(Imclear,B);
        end;
        //G.selected:=0;
        LastMarked:=0;
      end;
    end;
    //----------------------------------------------------------------------------
    //
    //----------------------------------------------------------------------------
    procedure TGraph.ReDraw();
    const
      border=20;
    var
      SB:TScrollBox;
    begin
      if (Length(CStream)>0) then begin
        Height:=Height-border;
        Width:=Width-border;
        if VWidth<Width then
          VWidth:=Width;
        if VHeight<Width then
          VHeight:=Height;
        //ScrollBox1.HorzScrollBar.Range:=GR.VWidth;//Opt.r.cfa.Sheet.Width;
        SB:=Im.parent as TScrollBox;
        SB.VertScrollBar.Range:=VHeight;//Opt.r.cfa.Sheet.Height;
        DrawGraph();
        SB.Realign;
        if Selected>0 then
          GraphPositbyNode(Selected,Im);
      end
      else
        Opt.r.CFA.Sheet.Hide
    end;
    //------------------------------------------------------------------
    //--
    //recreate Image                                               --
    //--
    //------------------------------------------------------------------
    procedure TGraph.Recreate(var Img:TImage;var B:TBitmap);
    begin
      try
        Img.Picture.Bitmap.FreeImage;
        Img.Picture.Bitmap.Assign(B);
        Img.Repaint;
      except
        On E:Exception do
          errorn(8,'Bitmap fehlerhaft, '+E.Message);
      end;
    end;
    //------------------------------------------------------------------
    //--
    //draw Grid                                                    --
    //--
    //------------------------------------------------------------------
    procedure TGraph.Grid(P:TPoint;DrawGrid:boolean);
    var
      sl,Sh:integer;
    begin
      if DrawGrid then begin //frame
        sl:=Sidelength div 2;
        Sh:=Sidelength div 2;
        B.Canvas.Pen.Style:=psDashDot;
        B.Canvas.Pen.Mode:=pmCopy;
        B.Canvas.Pen.color:=clLtGray;
        //B.Canvas.TextOut(P.X,P.Y,'x');
        B.Canvas.MoveTo(P.X-sl,P.Y-Sh);
        B.Canvas.LineTo(P.X-sl,P.Y+Sh);
        B.Canvas.LineTo(P.X+sl,P.Y+Sh);
        B.Canvas.LineTo(P.X+sl,P.Y-Sh);
        B.Canvas.LineTo(P.X-sl,P.Y-Sh);
      end;
    end;
    //------------------------------------------------------------------
    //--
    //draw Node                                                    --
    //--
    //------------------------------------------------------------------
    procedure TGraph.Vertex(Typ:NType;P:TPoint;T:JString;Mark:boolean;
      ou,pebbles:integer);
    var
      Txt:JString;
      i,ww,hh,cpl,Lines,verHeight,verwidth,normalwidth,normalheight:integer;
      overwidth,overheight:integer;
      Sh:TGraphShape;
      Rhomb: array [0..3] of TPoint;
      Ce:TPoint;
      ll,ci,ne:integer;
      fs:integer;
      lab:TPoint;
      fontfact:extended;
      //--------------------------------------------
      procedure placepebbles(PL,PT,PR,pb,num:integer;ofs:real;fs:integer);
      var
        i,L,T,w,h,fsh,maxc,maxu,rad:integer;
        phi:real;
        oc:Tcolor;
      begin
        oc:=B.Canvas.font.color;
        B.Canvas.font.color:=clRed;
        fs:=fs+1;
        repeat
          fs:=fs-1;
          fsh:=fs div 2;
          w:=(PR-PL);
          h:=(pb-PT);
          rad:=w div 2-fs;
          maxc:=rad div fs;
          maxu:=Floor(2*PI*rad/fs);
        until num<=maxc*maxu;
        if num>=0 then begin
          if num=1 then begin
            L:=PL+w div 2-fsh;
            T:=PT+h div 2-(3*fsh)div 2;
            B.Canvas.font.Size:=fs;
            B.Canvas.TextOut(L,T,'*');
          end
          else if num<=4 then begin
            phi:=ofs;
            for i:=1 to num do begin
              L:=PL+Floor(rad*sin(phi)/2)+(3*rad)div 2-fsh;
              T:=PT+Floor(rad*cos(phi)/2)+rad+fsh;
              B.Canvas.font.Size:=fs;
              B.Canvas.TextOut(L,T,'*');
              phi:=phi+2*PI/num;
            end;
          end
          else if num<=maxc*maxu+1 then begin
            phi:=ofs;
            for i:=1 to maxu do begin
              L:=PL+Floor(rad*sin(phi))+(3*rad)div 2-fsh;
              T:=PT+Floor(rad*cos(phi))+rad+fsh;
              B.Canvas.font.Size:=fs;
              B.Canvas.TextOut(L,T,'*');
              phi:=phi+2*PI/maxu;
            end;
            PL:=PL+fs;
            PR:=PR-fs;
            PT:=PT+fs;
            pb:=pb-fs;
            placepebbles(PL,PT,PR,pb,num-maxu,PI/maxu,fs);
          end
          else begin
            L:=PL+w div 2-fsh;
            T:=PT+h div 2-(3*fsh)div 2;
            B.Canvas.TextOut(L,T,'mehr');
          end;
        end;
        B.Canvas.font.color:=oc;
      end;
    //--------------------------------------------
    begin
      fontfact:=VWidth/Width;
      normalwidth:=4*diameter div 3;
      normalheight:=3*diameter div 4;
      overwidth:=3*normalwidth div 2;
      overheight:=3*normalheight div 2;
      if VWidth<Width then begin
        P.X:=P.X+VLeft;
        P.Y:=P.Y+VTop;
      end;
      Sh:=shElipse;
      lab.X:=P.X;
      lab.Y:=P.Y;
      //pen for frame of shape
      B.Canvas.Pen.Style:=psSolid;
      B.Canvas.Pen.Width:=Linethickness;
      B.Canvas.Pen.Mode:=pmCopy;
      B.Canvas.Pen.color:=opt.R.FontColor;
      B.Canvas.font.Size:=opt.R.FontSize;
      //brush for inside
      B.Canvas.Brush.Style:=bsSolid;
      //size of shape
      if Mark then begin
        verwidth:=overwidth;
        verHeight:=overheight;
      end
      else begin
        verwidth:=normalwidth;
        verHeight:=normalheight;
      end;
      case Typ of
        noitem:begin
            B.Canvas.Brush.color:=clOlive;
            Sh:=shElipse;
          end;
        numericitem:begin
            B.Canvas.Brush.color:=clBlue;
            Sh:=shRectangle;
          end;
        charitem:begin
            B.Canvas.Brush.color:=clRed;
            Sh:=shRectangle;
          end;
        functionitem,block:begin
            B.Canvas.Brush.color:=clFuchsia;
            if ou>1 then begin
              Sh:=shRhombus;
              B.Canvas.Brush.color:=clBlue
            end
            else begin
              Sh:=shRoundRectAngle;
              B.Canvas.Brush.color:=clRed
            end
          end;
        symbol:begin
            B.Canvas.Brush.color:=clNavy;
            if T=S_Human then
              Sh:=shHuman
            else if T=S_Database then
              Sh:=shDatabase
            else if T=S_Monitor then
              Sh:=shMonitor
            else
              Sh:=shRectangle;
          end;
        loopitem:begin
            B.Canvas.Brush.color:=clTeal;
            Sh:=shSquare;
          end;
        subtreeitem:begin
            B.Canvas.Brush.color:=clMaroon;
            Sh:=shElipse;
          end;
        assumedfunction:begin
            B.Canvas.Brush.color:=clRed;
            Sh:=shRoundRectAngle;
          end;
        assumedData:begin
            B.Canvas.Brush.color:=clRed;
            Sh:=shRectangle;
          end;
        transition:begin
            B.Canvas.Brush.color:=clBlack;
            Sh:=shBar;
          end;
        place:begin
            B.Canvas.Brush.color:=clBlack;
            Sh:=shCircle;
          end;
      end;
      if Typ=selection then begin
        ww:=5*diameter div 2;
        hh:=5*diameter div 2;
        B.Canvas.Brush.Style:=bsClear;
        B.Canvas.Pen.color:=clTeal;
        B.Canvas.Pen.Style:=psDash;
        B.Canvas.Pen.Mode:=pmXor;
        B.Canvas.Ellipse(P.X-ww,P.Y-hh,P.X+ww,P.Y+hh);
      end
      else if Typ=deselection then begin
        ww:=5*diameter div 2;
        hh:=5*diameter div 2;
        B.Canvas.Brush.Style:=bsClear;
        B.Canvas.Pen.color:=clTeal;
        B.Canvas.Pen.Style:=psDash;
        B.Canvas.Pen.Mode:=pmXor;
        B.Canvas.Ellipse(P.X-ww,P.Y-hh,P.X+ww,P.Y+hh);
      end
      else if Typ in [simstart,simwithin,simend,simcircle] then begin
        ww:=5*diameter div 2;
        hh:=5*diameter div 2;
        B.Canvas.Brush.Style:=bsClear;
        if Typ=simstart then
          B.Canvas.Pen.color:=clGreen
        else if Typ=simend then
          B.Canvas.Pen.color:=clRed
        else if Typ=simcircle then
          B.Canvas.Pen.color:=clPurple
        else
          B.Canvas.Pen.color:=clYellow;
        if Typ=simstart then
          B.Canvas.Pen.color:=clLime;
        B.Canvas.Pen.color:=B.Canvas.Pen.color xor opt.R.BackgroundColor;
        LastSim:=B.Canvas.Pen.color;
        B.Canvas.Pen.Style:=psDash;
        B.Canvas.Pen.Mode:=pmXor;
        B.Canvas.Pen.Width:=2*Linethickness;
        B.Canvas.Ellipse(P.X-ww,P.Y-hh,P.X+ww,P.Y+hh);
      end
      else if Typ=desimulation then begin
        ww:=5*diameter div 2;
        hh:=5*diameter div 2;
        B.Canvas.Brush.Style:=bsClear;
        B.Canvas.Pen.color:=LastSim;
        B.Canvas.Pen.Style:=psDash;
        B.Canvas.Pen.Mode:=pmXor;
        B.Canvas.Pen.Width:=2*Linethickness;
        B.Canvas.Ellipse(P.X-ww,P.Y-hh,P.X+ww,P.Y+hh);
      end
      else
        case Sh of
          shRectangle:begin
              ww:=3*verwidth div 4;
              hh:=3*verHeight div 4;
              lab.Y:=lab.Y+hh;
              B.Canvas.Brush.Style:=bsFDiagonal;
              B.Canvas.Rectangle(P.X-ww,P.Y-hh,P.X+ww,P.Y+hh);
            end;
          shRoundRectAngle:begin
              ww:=5*verwidth div 6;
              hh:=5*verHeight div 6;
              lab.Y:=lab.Y+hh;
              B.Canvas.Brush.Style:=bsFDiagonal;
              B.Canvas.RoundRect(P.X-ww,P.Y-hh,P.X+ww,P.Y+hh,ww,hh);
            end;
          shBar:begin
              ww:=verwidth div 6;
              hh:=3*verHeight div 2;
              lab.Y:=lab.Y+hh;
              B.Canvas.Brush.Style:=bsSolid;
              B.Canvas.Rectangle(P.X-ww,P.Y-hh,P.X+ww,P.Y+hh);
            end;
          shSquare:begin
              ww:=3*verwidth div 4;
              lab.Y:=lab.Y+ww;
              B.Canvas.Brush.Style:=bsFDiagonal;
              B.Canvas.Rectangle(P.X-ww,P.Y-ww,P.X+ww,P.Y+ww);
            end;
          shElipse:begin
              lab.Y:=lab.Y+verHeight;
              B.Canvas.Brush.Style:=bsCross;
              B.Canvas.Ellipse(P.X-verwidth,P.Y-verHeight,P.X+verwidth,
                P.Y+verHeight);
            end;
          shCircle:begin
              lab.Y:=lab.Y+verwidth;
              B.Canvas.Brush.Style:=bsClear;
              B.Canvas.Ellipse(P.X-verwidth,P.Y-verwidth,P.X+verwidth,
                P.Y+verwidth);
              placepebbles(P.X-verwidth,P.Y-verwidth,P.X+verwidth,P.Y+verwidth,
                pebbles,0,B.Canvas.font.Size);
            end;
          shRhombus:begin
              B.Canvas.Brush.Style:=bsCross;
              lab.Y:=lab.Y+verHeight;
              Rhomb[0].X:=P.X;
              Rhomb[0].Y:=P.Y+verHeight;
              Rhomb[1].X:=P.X+verwidth;
              Rhomb[1].Y:=P.Y;
              Rhomb[2].X:=P.X;
              Rhomb[2].Y:=P.Y-verHeight;
              Rhomb[3].X:=P.X-verwidth;
              Rhomb[3].Y:=P.Y;
              B.Canvas.Polygon(Rhomb);
            end;
          shHuman:begin
              ll:=max(verwidth,verHeight)div 3;
              ci:=2*ll div 3;//circle
              ne:=ll div 5;//neck
              Ce.X:=P.X;
              Ce.Y:=P.Y-ll;
              lab.Y:=lab.Y+ne+3*ll;
              B.Canvas.Brush.Style:=bsClear;
              //head
              B.Canvas.Ellipse(Ce.X-ci,Ce.Y-ci,Ce.X+ci,Ce.Y+ci);
              //neck
              B.Canvas.MoveTo(Ce.X,Ce.Y+ci);
              B.Canvas.LineTo(Ce.X,Ce.Y+ci+ne);
              //body
              B.Canvas.MoveTo(Ce.X,Ce.Y+ci+ne);
              B.Canvas.LineTo(Ce.X,Ce.Y+ne+2*ll);
              //arms
              B.Canvas.MoveTo(Ce.X-ll,Ce.Y+ci+ne);
              B.Canvas.LineTo(Ce.X+ll,Ce.Y+ci+ne);
              //legs
              B.Canvas.MoveTo(Ce.X,Ce.Y+ne+2*ll);
              B.Canvas.LineTo(Ce.X-ll,Ce.Y+ne+3*ll);
              B.Canvas.MoveTo(Ce.X,Ce.Y+ne+2*ll);
              B.Canvas.LineTo(Ce.X+ll,Ce.Y+ne+3*ll);
            end;
          shDatabase:begin
              ww:=verwidth;
              hh:=verHeight;
              ll:=min(2*ww,2*hh)div 2;
              lab.Y:=lab.Y+ll div 2;
              B.Canvas.Brush.Style:=bsClear;
              //top
              B.Canvas.Ellipse(P.X-ll,P.Y-3*ll div 2,P.X+ll,P.Y-ll div 2);
              //left
              B.Canvas.MoveTo(P.X-ll,P.Y-ll);
              B.Canvas.LineTo(P.X-ll,P.Y+ll);
              //right
              B.Canvas.MoveTo(P.X+ll,P.Y-ll);
              B.Canvas.LineTo(P.X+ll,P.Y+ll);
              //bottom
              B.Canvas.Ellipse(P.X-ll,P.Y+3*ll div 2,P.X+ll,P.Y+ll div 2);
            end;
          shMonitor:begin
              ll:=min(2*verwidth,2*verHeight)div 2;
              hh:=2*ll div 3;
              lab.Y:=lab.Y+2*hh div 3;
              B.Canvas.Brush.Style:=bsClear;
              //screen
              B.Canvas.Rectangle(P.X-ll,P.Y-ll,P.X+ll,P.Y+ll);
              B.Canvas.RoundRect(P.X-3*ll div 4,P.Y-3*ll div 4,P.X+3*ll div 4,
                P.Y+3*ll div 4,3*ll div 4,3*ll div 4);
              //keyboard
              B.Canvas.MoveTo(P.X-ll,P.Y+ll);
              B.Canvas.LineTo(P.X-2*ll,P.Y+ll+hh);
              B.Canvas.MoveTo(P.X+ll,P.Y+ll);
              B.Canvas.LineTo(P.X,P.Y+ll+hh);
              B.Canvas.MoveTo(P.X-2*ll,P.Y+ll+hh);
              B.Canvas.LineTo(P.X,P.Y+ll+hh);
              B.Canvas.MoveTo(P.X-2*ll div 3,P.Y+ll+hh div 3);
              B.Canvas.LineTo(P.X,P.Y+ll+hh div 3);
              B.Canvas.MoveTo(P.X-2*2*ll div 3,P.Y+ll+2*hh div 3);
              B.Canvas.LineTo(P.X,P.Y+ll+2*hh div 3);
            end;
        end;
      //pen
      B.Canvas.Pen.Style:=psSolid;
      B.Canvas.Pen.color:=opt.R.FontColor;
      B.Canvas.Pen.Width:=Linethickness;
      B.Canvas.Pen.Mode:=pmBlack;
      //brush
      B.Canvas.Brush.color:=opt.r.BackgroundColor;
      B.Canvas.Brush.Style:=bsSolid;
      //font  and characters per line
      //B.Canvas.font.Name:=FontName;
      //B.Canvas.font.color:=FontColor;
      //B.Canvas.font.Style:=FontStyle;
      fs:=min(round(fontfact*opt.r.fontsize),2*diameter div 3);
      B.Canvas.font.Size:=fs;
      cpl:=diameter div 2;//characters per line
      if (not(Typ in [selection,deselection,desimulation,simstart,simwithin,
          simend,simcircle]))and(Length(T)>0) then begin
        i:=1;
        Lines:=1;
        while (i<=Length(T))and(Lines<=2) do begin
          while (T[i]=' ')and(i<Length(T)-1) do
            i:=i+1;
          if Lines=2 then
            cpl:=cpl-3;
          Txt:=Trim(MidStr(T,i,cpl));
          if (Lines=2)and(i+cpl<Length(T)) then
            Txt:=Txt+'...';
          i:=i+cpl;
          B.Canvas.TextOut(lab.X+fs div 2,lab.Y+(Lines-1)*6*fs div 4,Txt);
          Lines:=Lines+1;
        end;
      end;
      B.Canvas.font.Size:=opt.r.fontsize;
    end;
    //------------------------------------------------------------------
    //--
    //determine Coordinates                                        --
    //--
    //------------------------------------------------------------------
    function TGraph.PointCoordinates(n:integer):TPoint;
    var
      X,Y,YM,XM:variant;
      P:TPoint;
    begin
      XM:=max(1,(VWidth-2*XBorder)div Sidelength);
      YM:=max(1,(VHeight-2*YBorder)div Sidelength);
      X:=Sidelength div 2+((n-1)mod XM)*Sidelength;
      Y:=Sidelength div 2+((n-1)div XM)*Sidelength;
      P.X:=X+XBorder;
      P.Y:=Y+YBorder;
      PointCoordinates:=P
    end;
    //------------------------------------------------------------------
    //--
    //get Type of Node                                             --
    //--
    //------------------------------------------------------------------
    function TGraph.GetNodeTyp(S:JString;var ini:integer):NType;
    var
      NTyp,j:NType;
      NDur,L:NDuration;
      Sea:JString;
      NBas:NBase;
      k:NBase;
    begin
      NTyp:=noitem;
      Sea:=getattribute(S_Typ,S);
      for j:= Low(NType) to High(NType) do
        if Pos(S_Ntype[j],Sea)>0 then
          NTyp:=j;
        NDur:=static;
        Sea:=getattribute(S_Dur,S);
        for L:= Low(NDuration) to High(NDuration) do
          if Pos(S_NDurations[L],Sea)>0 then
            NDur:=L;
        if NDur=firing then begin
          NTyp:=place;
          Sea:=getattribute(S_Init,S);
          TryStrtoInt(Sea,ini);
        end
        else if NDur=synchronized then
          NTyp:=transition
        else if (NTyp=numericitem)or(NTyp=charitem) then begin
          Sea:=getattribute(S_Bas,S);
          NBas:=nobase;
          for k:= Low(NBase) to High(NBase) do
            if Pos(S_NBases[k],Sea)>0 then
              NBas:=k;
          if NBas=octet then
            NTyp:=charitem
          else
            NTyp:=numericitem;
      end;
      GetNodeTyp:=NTyp
    end;
    //------------------------------------------------------------------
    //--
    //determine Graph Size                                         --
    //--
    //------------------------------------------------------------------
    procedure TGraph.DetermineGraphSize();
    const
      minsize=100;
      minsidelength=6;
    var
      Corrector:variant;
      XM,YM,Rest:integer;
      fontfact,sl:extended;
      P:TPoint;
    begin
      fontfact:=VWidth/Width;
      if fontfact=0 then
        fontfact:=1;
      B:=TBitmap.Create;
      B.Canvas.Brush.color:=opt.r.BackgroundColor;
      if (VWidth<minsize) then
        VWidth:=minsize;
      if (VHeight<minsize) then
        VHeight:=minsize;
      B.Width:=VWidth;
      B.Height:=VHeight;
      Corrector:=-1;
      XBorder:=VWidth div 20;
      YBorder:=VHeight div 20;
      if fontfact<0.9 then begin
        XBorder:=XBorder+(Width-VWidth)div 2;
        YBorder:=YBorder+(Height-VHeight)div 2;
      end;
      Repeat
        Corrector:=Corrector+1;
        sl:=VWidth*VHeight-2*VWidth*YBorder-2*VHeight*XBorder;
        if Verticecount>0 then begin
          sl:=max(3,sl/Verticecount);
          Sidelength:=sqrt(sl)-Corrector
        end
        else
          Sidelength:=VWidth-2*XBorder;
        Sidelength:=min(Sidelength,min(VWidth div 2,VHeight div 2));
        Sidelength:=max(minsidelength,Sidelength);
        diameter:=Sidelength/6;
        diameter:=max(1,diameter);
        XM:=max(1,(VWidth-2*XBorder)div Sidelength);
        YM:=max(1,(VHeight-2*YBorder)div Sidelength)
      until (XM*YM>=Verticecount)or(Corrector>2*Sidelength);
      P:=PointCoordinates(Verticecount);
      if (P.X-Sidelength div 2>max(VWidth,Width))or
        (P.Y-Sidelength div 2>max(VHeight,Height)) then begin
        VWidth:=2*max(VWidth,Width);
        VHeight:=2*max(VHeight,Height);
        //errorn(5,'Graph hat zuviele Elemente');
      end;
      Sidelength:=min(Sidelength,2*7*opt.r.fontsize);
      diameter:=Sidelength/6;
      //correct small graphs
      if (VWidth<Width)and(VHeight<Height) then begin
        XBorder:=XBorder+(VWidth-VWidth)div 2;
        YBorder:=YBorder+(VHeight-VHeight)div 2;
      end;
      //another corrector
      if (VWidth>=Width)and(VHeight>=Height) then begin
        Rest:=(VWidth-2*XBorder)-XM*Sidelength;
        if Rest>Sidelength then
          XBorder:=XBorder+Rest div 2;
        Rest:=(VHeight-2*YBorder)-YM*Sidelength;
        if Rest>Sidelength then
          YBorder:=YBorder+Rest div 2;
      end;
      //minimum?
      if Sidelength<minsize div 2 then
        Linethickness:=1;
      //B.Canvas.font.Name:=FontName;
      B.Canvas.font.Size:=opt.r.fontsize;
    end;
    //------------------------------------------------------------------
    //--
    //draw Edge                                                    --
    //--
    //------------------------------------------------------------------
    procedure TGraph.Edge(O,G:TPoint;T:JString;multiple:boolean);
    var
      dist,dx,dy,angle,Cathy:variant;
      Org,Goal:TPoint;
    begin
      Org:=O;
      Goal:=G;
      //O=origin G=goal
      dist:=sqrt(sqr(G.Y-O.Y)+sqr(G.X-O.X));
      if (dist>0) then begin
        dx:=diameter*(G.X-O.X)/dist/2;
        dy:=diameter*(G.Y-O.Y)/dist/2;
        if (G.Y<>O.Y) then begin
          O.X:=O.X+dx+VLeft;
          G.X:=G.X-dx+VLeft
        end
        else begin
          if G.X>O.X then begin
            O.X:=O.X+diameter+VLeft;
            G.X:=G.X-diameter+VLeft
          end
          else begin
            O.X:=O.X-diameter+VLeft;
            G.X:=G.X+diameter+VLeft;
          end
        end;
        if (G.X<>O.X) then begin
          O.Y:=O.Y+dy+VTop;
          G.Y:=G.Y-dy+VTop;
        end
        else begin
          if G.Y>O.Y then begin
            O.Y:=O.Y+diameter+VTop;
            G.Y:=G.Y-diameter+VTop
          end
          else begin
            O.Y:=O.Y-diameter+VTop;
            G.Y:=G.Y+diameter+VTop
          end
        end;
        dist:=sqrt(sqr(G.Y-O.Y)+sqr(G.X-O.X));
        Cathy:=G.Y-O.Y;
        angle:=arcsin(-(Cathy)/dist);
        //---------------
        //
        //Q2      Q1
        //
        //Q3      Q4
        //
        //---------------
        //zuerst die schrägen Winkel
        if (G.Y<O.Y)and(G.X>O.X) then
          angle:=angle+PI/2//Q1
        else if (G.Y<O.Y)and(G.X<O.X) then
          angle:=3*PI/2-angle//Q2
        else if (G.Y>O.Y)and(G.X<O.X) then
          angle:=-angle-PI/2//Q3
        else if (G.Y>O.Y)and(G.X>O.X) then
          angle:=angle+2*PI+PI/2//Q4
          //dann die rechten Winkel
        else if (G.Y=O.Y)and(G.X<=O.X) then
          angle:=angle-PI/2//Y links
        else if (G.Y=O.Y)and(G.X>O.X) then
          angle:=angle+PI/2//Y rechts
        else if (G.X=O.X)and(G.Y>=O.Y) then
          angle:=angle+PI/2//X oben
        else if (G.X=O.X)and(G.Y<O.Y) then
          angle:=angle+PI/2;//X unten
        LabelEdge(Org,Goal,T);
        if multiple then
          DrawConnectParallelLine(Org,Goal,angle)
        else
          DrawConnectLine(O,G,angle);
      end
      else begin
        LabelEdge(Org,Org,T);
        DrawConnectCircle(Org)
      end;
    end;
    //------------------------------------------------------------------
    //--
    //draw Grid                                                    --
    //--
    //------------------------------------------------------------------
    procedure TGraph.LabelEdge(O,G:TPoint;T:JString);
    var
      i,fs,cpl,Lines:integer;
      Txt:JString;
      Ce:TPoint;
      fontfact:extended;
      bgcolor,diff:Tcolor;
      dist:integer;
    begin
      if Length(T)>0 then begin
        fontfact:=(VWidth/Width)*8/10;
        //compute color
        diff:=40;
        bgcolor:=clLtGray+(diff+256*(diff+256*diff));
        //pen
        B.Canvas.Pen.Style:=psSolid;
        B.Canvas.Pen.color:=clWhite;
        B.Canvas.Pen.Width:=Linethickness;
        B.Canvas.Pen.Mode:=pmWhite;
        //brush
        B.Canvas.Brush.color:=bgcolor;
        B.Canvas.Brush.Style:=bsSolid;
        //font  and characters per line
        //B.Canvas.font.Name:=FontName;
        //B.Canvas.font.color:=FontColor;
        //B.Canvas.font.Style:=FontStyle;
        fs:=min(round(fontfact*opt.r.fontsize),2*diameter div 2);
        B.Canvas.font.Size:=fs;
        cpl:=diameter div 2;//characters per line
        dist:=10;
        if (O.X=G.X)and(O.Y=G.Y) then begin
          Ce.X:=O.X+10;
          Ce.Y:=O.Y+10;
        end
        else begin
          if G.X>O.X then
            Ce.X:=O.X+(G.X-O.X)div 2
          else
            Ce.X:=G.X+(O.X-G.X)div 2;
          if G.Y>O.Y then
            Ce.Y:=O.Y+(G.Y-O.Y)div 2
          else
            Ce.Y:=G.Y+(O.Y-G.Y)div 2;
          if G.Y>O.Y then begin
            Ce.Y:=Ce.Y-fs;
            Ce.X:=Ce.X-Length(T)*fs div 2
          end;
          Ce.X:=Ce.X+dist;
          Ce.Y:=Ce.Y+dist;
        end;
        i:=1;
        Lines:=1;
        while (i<=Length(T))and(Lines<=2) do begin
          while (T[i]=' ')and(i<Length(T)-1) do
            i:=i+1;
          if Lines=2 then
            cpl:=cpl-3;
          Txt:=Trim(MidStr(T,i,cpl));
          if (Lines=2)and(i+cpl<Length(T)) then
            Txt:=Txt+'...';
          i:=i+cpl;
          B.Canvas.TextOut(Ce.X+fs div 2,Ce.Y+(Lines-1)*6*fs div 4,Txt);
          Lines:=Lines+1;
        end;
      end;
    end;
    //------------------------------------------------------------------
    //--
    //determine Coordinates                                        --
    //--
    //------------------------------------------------------------------
    procedure TGraph.PCo(r:TRect;n:integer;O:boolean);
    var
      i,P:integer;
      RS:TRect;
    begin
      i:=n-1;
      P:=0;
      while (i>0)and(P=0) do begin
        if (n mod i=0) then
          if Prime(i) then
            P:=i;
        i:=i-1
      end;//p = largest prime
      RS:=r;
      if P>1 then begin
        if O then begin
          RS.left:=0;
          RS.right:=r.right div P;
        end
        else begin
          RS.top:=0;
          RS.bottom:=r.bottom div P
        end;
        PCo(RS,n div P,not O);
      end;
    end;
    //------------------------------------------------------------------
    //--
    //draw beginning of Arrow                                      --
    //--
    //------------------------------------------------------------------
    procedure TGraph.Arrowstart(var B:TBitmap;P:TPoint;A:real;L:integer);
    var
      r,Q:TPoint;
      A1,A2,A3,S:variant;
    begin
      A1:=A;
      A2:=A1-PI/9;
      A3:=A1+PI/9;
      S:=sqrt(L*L/2+L*L/2);
      r.X:=P.X-S*sin(A2);
      r.Y:=P.Y-S*cos(A2);
      Q.X:=P.X-S*sin(A3);
      Q.Y:=P.Y-S*cos(A3);
      B.Canvas.Pen.Width:=Linethickness;
      B.Canvas.MoveTo(P.X,P.Y);
      B.Canvas.LineTo(r.X,r.Y);
      B.Canvas.MoveTo(P.X,P.Y);
      B.Canvas.LineTo(Q.X,Q.Y);
      //B.Canvas.LineTo(P.X,P.Y);
    end;
    //------------------------------------------------------------------
    //--
    //draw End of Arrow                                            --
    //--
    //------------------------------------------------------------------
    procedure TGraph.Arrowend(var B:TBitmap;P:TPoint;A:real;L:integer);
    var
      r,Q:TPoint;
      A1,A2,A3,S:variant;
    begin
      A1:=A;
      A2:=A1-PI/9;
      A3:=A1+PI/9;
      S:=sqrt(L*L/2+L*L/2);
      r.X:=P.X-S*sin(A2);
      r.Y:=P.Y-S*cos(A2);
      Q.X:=P.X-S*sin(A3);
      Q.Y:=P.Y-S*cos(A3);
      B.Canvas.Pen.Width:=Linethickness;
      B.Canvas.MoveTo(P.X,P.Y);
      B.Canvas.LineTo(r.X,r.Y);
      B.Canvas.LineTo(Q.X,Q.Y);
      B.Canvas.LineTo(P.X,P.Y);
    end;
    //------------------------------------------------------------------
    //--
    //draw Arc                                                     --
    //--
    //------------------------------------------------------------------
    procedure TGraph.DrawConnectArc(O,G:TPoint;angle:variant);
    const
      bow=5/2;
    var
      P1,P2,P3,P4,P5,CC:TPoint;
      BoundRect:TRect;
      dist,radius:integer;
      procedure Correct;
      var
        sect:integer;
      begin
        sect:=diameter div 2;
        if P4.X=P3.X then begin
          if P4.Y>=P3.Y then begin
            P3.X:=P3.X-sect;
            P4.X:=P4.X-sect;
            P3.Y:=P3.Y+sect;
            P4.Y:=P4.Y-sect
          end
          else begin
            P3.X:=P3.X+sect;
            P4.X:=P4.X+sect;
            P3.Y:=P3.Y-sect;
            P4.Y:=P4.Y+sect
          end;
        end
        else if P4.Y=P3.Y then begin
          if P4.X>=P3.X then begin
            P3.Y:=P3.Y+sect div 2;
            P4.Y:=P4.Y+sect;
            P3.X:=P3.X+sect;
            P4.X:=P4.X-sect
          end
          else begin
            P3.Y:=P3.Y-sect;
            P4.Y:=P4.Y-sect;
            P3.X:=P3.X-sect;
            P4.X:=P4.X+sect
          end
        end
        else if P4.X>P3.X then begin
          P3.X:=P3.X+sect;
          P4.X:=P4.X;
          if P4.Y>P3.Y then begin
            P3.Y:=P3.Y+sect;
            P4.Y:=P4.Y-sect
          end
          else begin
            P3.Y:=P3.Y;
            P4.Y:=P4.Y
          end
        end
        else if P4.X<P3.X then begin
          P3.X:=P3.X-sect;
          P4.X:=P4.X;
          if P4.Y>P3.Y then begin
            P3.Y:=P3.Y;
            P4.Y:=P4.Y
          end
          else begin
            P3.Y:=P3.Y-sect;
--> --------------------

--> maximum size reached

--> --------------------

¤ Dauer der Verarbeitung: 0.75 Sekunden  (vorverarbeitet)  ¤





Druckansicht
unsichere Verbindung
Druckansicht
sprechenden Kalenders

in der Quellcodebibliothek suchen




Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.


Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.


Bot Zugriff



                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik