(* $R- $S- $V- *)

MODULE KuchenDemo;

(* Erstellen einer Kuchengrafik  by Holger Gzella *)

FROM Arts      IMPORT Assert;
FROM SYSTEM    IMPORT ADR,ADDRESS,INLINE,FFP;
FROM Exec      IMPORT GetMsg,ReplyMsg;
FROM Intuition IMPORT NewWindow,WindowPtr,OpenWindow,CloseWindow,IDCMPFlags,
                      IDCMPFlagSet,WindowFlags,ScreenFlags,ScreenFlagSet,
                      WindowFlagSet,OpenScreen,CloseScreen,NewScreen,
                      customScreen,ScreenPtr,IntuiMessagePtr;
FROM Graphics  IMPORT RastPortPtr,ViewModes,Move,Draw,ViewModeSet,
                      SetAPen,jam1,SetDrMd;
FROM MathTrans IMPORT Sin,Cos;

CONST pi = 3.1415;

VAR MeinWindow               : WindowPtr;
    MeinScreen               : ScreenPtr;
    RastPort                 : RastPortPtr;
    WindowDaten              : NewWindow;
    ScreenDaten              : NewScreen;
    Nachricht                : IntuiMessagePtr;
    class                    : IDCMPFlagSet;
    num,xnum,ynum            : INTEGER;
    wstp,bw,ew,wa,pr,w,su    : FFP;
    xm,ym,xr,yr,i,x1,y1,x2,y2: INTEGER;
    values                   : ARRAY[0..100] OF FFP;

(* Dies ist eine Routine, die das Zeichnen einer Ellipse *)
(* bzw. eines Ellipsenausschnittes übernimmt. Folgende   *)
(* Parameter werden gebraucht ...                        *)
(*                                                       *)
(* rp   - Zeiger auf den entsprechenden RastPort.        *)
(* xm   - x-Koordinate des Ellipsenmittelpunktes.        *)
(* ym   - y-Koordinate des Ellipsenmittelpunktes.        *)
(* xr   - x-Radius der Ellipse.                          *)
(* yr   - y-Radius der Ellipse.                          *)
(* bew  - Startwinkel der Ellipse.                       *)
(* enw  - Endwinkel der Ellipse.                         *)
(* wstp - Winkelschrittweite für's Zeichnen.             *)

PROCEDURE NewDrawEllipse(rp: RastPortPtr; xm,ym,xr,yr: INTEGER;
                         bew,enw,wstp: FFP);

VAR w: FFP;

  BEGIN

    w:=bew;
    x2:=INTEGER(FFP(xr)*Cos(0.0)+FFP(xm));      (* Koordinaten bestimmen *)
    y2:=INTEGER(FFP(yr)*Sin(0.0)+FFP(ym));

    REPEAT
      x1:=INTEGER(FFP(xr)*Cos(w)+FFP(xm));      (*           "           *)
      y1:=INTEGER(FFP(yr)*Sin(w)+FFP(ym));

      Move(rp,x2,y2);                           (* Ellipsenabschnitt     *)
      Draw(rp,x1,y1);                           (* mit Draw zeichnen ... *)

      x2:=x1;
      y2:=y1;

      w:=w+wstp;                                (* Zähler erhöhen ...    *)
    UNTIL w>enw+wstp;

  END NewDrawEllipse;

BEGIN

  WITH ScreenDaten DO
    leftEdge:=0; topEdge:=0; width:=640; height:=256; depth:=2;
    detailPen:=2; blockPen:=1; viewModes:=ViewModeSet{hires};
    type:=customScreen; font:=NIL; customBitMap:=NIL; gadgets:=NIL;
    defaultTitle:=ADR("*** BEISPIEL - STATISTIK ... ***");
  END;

  WITH WindowDaten DO
    leftEdge:=0; topEdge:=11; width:=640; height:=245; detailPen:=0;
    blockPen:=1; idcmpFlags:=IDCMPFlagSet{closeWindow}; firstGadget:=NIL;
    flags:=WindowFlagSet{windowDrag,windowDepth,windowClose,activate,
    gimmeZeroZero}; title:=ADR("Statistik-Window ..."); screen:=NIL;
    checkMark:=NIL; bitMap:=NIL; type:=customScreen;
  END;

  MeinScreen:=OpenScreen(ScreenDaten);
  Assert(MeinScreen#NIL,ADR("Kein Speicher für den Screen!"));

  WindowDaten.screen:=MeinScreen;
  MeinWindow:=OpenWindow(WindowDaten);
  Assert(MeinWindow#NIL,ADR("Kein Speicher für's Window!"));
  RastPort:=MeinWindow^.rPort;

  SetDrMd(RastPort,jam1);
  SetAPen(RastPort,1);

  (* An dieser Stelle werden die einzelnen Werte initialisiert ... *)

  values[0]:=16.0; values[1]:=16.5; values[2]:=15.5;
  values[3]:=20.0; values[4]:=16.0; values[5]:=16.0;

  num:=6;                                       (* Anzahl Werte    *)
  xm:=320;                                      (* x-Mittelpunkt   *)
  ym:=128;                                      (* y-Mittelpunkt   *)
  xr:=200;                                      (* x-Radius        *)
  yr:=70;                                       (* y-Radius        *)

  wstp:=7.0*pi/180.0;                           (* Winkelschritte  *)
  bw:=0.0;                                      (* Startwinkel     *)
  ew:=pi*2.0;                                   (* Endwinkel       *)

  (* Nun wird eine Torte gezeichnet ... *)

  NewDrawEllipse(RastPort,xm,ym,xr,yr,bw,ew,wstp);

  bw:=0.0;
  ew:=pi*1.03;

  NewDrawEllipse(RastPort,xm,ym+17,xr,yr,bw,ew,wstp);

  Move(RastPort,120,128);
  Draw(RastPort,120,145);
  Move(RastPort,520,128);
  Draw(RastPort,520,145);

  FOR i:=0 TO num-1 DO                          (* Summe aller     *)
    su:=su+values[i];                           (* Werte bilden!   *)
  END;

  (* Jetzt kommen die einzelnen Tortenstücke 'dran ... *)

  FOR i:=0 TO num-1 DO
    pr:=values[i]/su;                           (* Prozentanteil   *)
                                                (* am Ganzen       *)
    wa:=2.0*pi*pr;                              (* Winkel berech-  *)
    w:=w+wa;                                    (* nen ...         *)
    x1:=INTEGER(FFP(xr)*Cos(w)+FFP(xm));        (* Koordinaten     *)
    y1:=INTEGER(FFP(yr)*Sin(w)+FFP(ym));        (* berechnen ...   *)

    Move(RastPort,xm,ym);                       (* Trennlinie      *)
    Draw(RastPort,x1,y1);                       (* zeichnen ...    *)

    (* Auf der dem Betrachter zugewandten Seite sollen die   *)
    (* Tortenstücke auch dreidimensional dargestellt werden! *)

    IF w<=pi THEN
      x2:=x1;
      y2:=y1;
      x1:=INTEGER(FFP(xr)*Cos(w)+FFP(xm));      (* Koordinaten     *)
      y1:=INTEGER(FFP(yr+17)*Sin(w)+FFP(ym));   (* berechnen ...   *)

      Move(RastPort,x2,y2);                     (* Und Trennlinie  *)
      Draw(RastPort,x1,y1);                     (* zeichnen ...    *)
    END;
  END;

  LOOP
    Nachricht:=GetMsg(MeinWindow^.userPort);
    WHILE Nachricht#NIL DO
      class:=Nachricht^.class;
      ReplyMsg(Nachricht);
      IF (closeWindow IN class) THEN EXIT; END;
      Nachricht:=GetMsg(MeinWindow^.userPort);
    END;
  END;

  CloseWindow(MeinWindow);
  CloseScreen(MeinScreen);

END KuchenDemo.
