// Module PI : Peida Interactive     PIGraphicX
// Trace graphiques- Implementation X11  R. Ansari  97
// LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA

#include <stdio.h>
#include <math.h>

#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>

#include "pigraphx.h"


/*  Variables globales pour modifier les GC  */
#define NMAXCOL  24
static  PIXColor colpix[NMAXCOL];

/*  GC pour DrawPixmap   */
static GC dpxgc;

// #define DEBUG_PIBWDGX     Flag pour impression de debug etc ...

/* --Methode-- */
PIGraphicX::PIGraphicX(PIWdg* wdg)
: PIGraphicGen(wdg)
{

GlInit();

if (MyWdg()) {
  mDisp = XtDisplay(MyWdg());       // Structure Display X associe
  mWId = XtWindow(MyWdg());   // Le drawable X
  }
else mDisp = PIXDisplay();       // Structure Display X associe

XGCValues  xgv;
xgv.function = GXcopy;
xgv.plane_mask = ~0;
mDefGC = XCreateGC (PIXDisplay(), XtWindow(PIXtTopWdg()), GCFunction | GCPlaneMask, &xgv);

Init();
}

/* --Methode-- */
PIGraphicX::PIGraphicX(PIScreenBuffer* grb)
: PIGraphicGen(grb)
{
GlInit();

mDisp = PIXDisplay();       // Structure Display X associe
mWId = grb->XScrBuffer();

XGCValues  xgv;
xgv.function = GXcopy;
xgv.plane_mask = ~0;
mDefGC = XCreateGC (mDisp, mWId, GCFunction | GCPlaneMask, &xgv);
Init();
}


/* --Methode-- */
void PIGraphicX::Init()
{
mGOm = PI_GOCopy;
mFCol = mBCol = PI_Grey;
SelForeground(PI_Black);
SelBackground(PI_White);
mLAtt = PI_ThinLine;
 XSetFont(mDisp, DefGC(), myFont.GetXFontId());  // Pour initialiser la fonte ds le GC 
SelLine();
SelMarker(1, PI_DotMarker);  
mFCfMap = colpix[PI_Black];  mBCfMap = colpix[PI_White];
}

/* --Methode-- */
PIGraphicX::~PIGraphicX()
{
XFreeGC(mDisp, mDefGC);
}

/* --Methode-- */
int PIGraphicX::kind()
{
if (myWdg != NULL) return (PI_ScrWindowGraphics);
else if (myGrb != NULL) return (PI_ScrBufferGraphics);
else return(PI_UnknownGraphics);
}

/* --Methode-- */
void PIGraphicX::TerminateInit()
{
if (MyWdg() == NULL)  { fprintf(stderr, "BUG/PIGraphicX::TerminateInit() for NULL Wdg \n"); return; }
mDisp = XtDisplay(MyWdg());       // Structure Display X associe
mWId = XtWindow(MyWdg());   // Le drawable X
}

/* --Methode-- */
void PIGraphicX::Erase(PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy)
{
XClearArea (mDisp,mWId, (int)x0, (int)y0, (int)dx, (int)dy, False );
return;
}

/* --Methode-- */
void PIGraphicX::DrawString(PIGrCoord x, PIGrCoord y, const char* s, int /*pos*/)
{
XDrawString (XtDisplay (MyWdg()),mWId, 
                  DefGC(), (int)x, (int)y, s, strlen(s));
return;
}

/* --Methode-- */
void PIGraphicX::DrawOpaqueString(PIGrCoord x, PIGrCoord y, const char* s, int /*pos*/)
{
XDrawImageString (XtDisplay (MyWdg()),mWId, 
                  DefGC(), (int)x, (int)y, s, strlen(s));
return;
}

 
/* --Methode-- */
void PIGraphicX::DrawLine(PIGrCoord x1, PIGrCoord y1, PIGrCoord x2, PIGrCoord y2)
{
XDrawLine(XtDisplay (MyWdg()), mWId, DefGC(), (int)x1, (int)y1, (int)x2, (int)y2);
return;
}


/* --Methode-- */
void PIGraphicX::DrawBox(PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy)
{
int ix0 = x0;
int iy0 = y0;
int idx = dx;
int idy = dy;
if (idx < 0)  { ix0 += idx;  idx = -idx; }
if (idy < 0)  { iy0 += idy;  idy = -idy; }
XDrawRectangle(XtDisplay (MyWdg()), mWId, 
               DefGC(), ix0, iy0, idx, idy);
return;
}

/* --Methode-- */
void PIGraphicX::DrawFBox(PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy)
{
int ix0 = x0;
int iy0 = y0;
int idx = dx;
int idy = dy;
if (idx < 0)  { ix0 += idx;  idx = -idx; }
if (idy < 0)  { iy0 += idy;  idy = -idy; }
XFillRectangle(XtDisplay (MyWdg()), mWId, 
               DefGC(), ix0, iy0, idx, idy);
return;
}

/* --Methode-- */
void PIGraphicX::DrawCircle(PIGrCoord x0, PIGrCoord y0, PIGrCoord r)
{
XDrawArc(XtDisplay (MyWdg()), mWId, DefGC(),
         (int)x0-(int)r, (int)y0-(int)r, 2*(int)r, 2*(int)r, 0, 360*64);
return;
}

/* --Methode-- */
void PIGraphicX::DrawFCircle(PIGrCoord x0, PIGrCoord y0, PIGrCoord r)
{
XFillArc(XtDisplay (MyWdg()), mWId, DefGC(),
         (int)x0-(int)r, (int)y0-(int)r, 2*(int)r, 2*(int)r, 0, 360*64);
return;
}

/* --Methode-- */
void PIGraphicX::DrawOval(PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy)
{
XDrawArc(XtDisplay (MyWdg()), mWId, DefGC(),
         (int)x0, (int)y0, (int)dx, (int)dy, 0, 360*64);
return;
}

/* --Methode-- */
void PIGraphicX::DrawFOval(PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy)
{
XFillArc(XtDisplay (MyWdg()), mWId, DefGC(),
         (int)x0, (int)y0, (int)dx, (int)dy, 0, 360*64);
return;
}

// Pour les fonctions de trace avec un plusieurs coordonnees
#define NMXXPOINTS  30 

/* --Methode-- */
void PIGraphicX::DrawPolygon(PIGrCoord *x, PIGrCoord *y, int n, bool cinc)
{
XPoint multipoint[NMXXPOINTS];
XPoint *pxp;
int i;

if (n <= 0)  return;
if (n > NMXXPOINTS)  pxp = new XPoint[n];
else pxp = multipoint;
for(i=0; i<n; i++)  { pxp[i].x = x[i];  pxp[i].y = y[i]; } 
int mode = CoordModeOrigin;
if (cinc) mode =  CoordModePrevious;
XDrawLines(mDisp, mWId, DefGC(), pxp, n, mode);
if (n > NMXXPOINTS)  delete[] pxp;

return;
}


/* --Methode-- */
void PIGraphicX::DrawFPolygon(PIGrCoord *x, PIGrCoord *y, int n, bool cinc)
{
XPoint multipoint[NMXXPOINTS];
XPoint *pxp;
int i;

if (n <= 0)  return;
if (n > NMXXPOINTS)  pxp = new XPoint[n];
else pxp = multipoint;
for(i=0; i<n; i++)  { pxp[i].x = x[i];  pxp[i].y = y[i]; } 
int mode = CoordModeOrigin;
if (cinc) mode =  CoordModePrevious;
XFillPolygon(XtDisplay (MyWdg()), mWId, DefGC(), pxp, n, 
                        Complex, mode);
if (n > NMXXPOINTS)  delete[] pxp;

return;
}

/* --Methode-- */
void PIGraphicX::DrawArc(PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy, 
                         double degdeb, double degfin)
{
XDrawArc(XtDisplay (MyWdg()), mWId, DefGC(),
         (int)x0, (int)y0, (int)dx, (int)dy, (int)(degdeb*64.), (int)(degfin*64.));
return;
}

/* --Methode-- */
void PIGraphicX::DrawFArc(PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy, 
                         double degdeb, double degfin)
{
XFillArc(XtDisplay (MyWdg()), mWId, DefGC(),
         (int)x0, (int)y0, (int)dx, (int)dy, (int)(degdeb*64.), (int)(degfin*64.));
return;
}

// Coordonnees pour tracer une etoile a 5 branches 
static float starcoordx[10], starcoordy[10];

/* --Methode-- */
void PIGraphicX::DrawMarker(PIGrCoord x0, PIGrCoord y0)
{
float hmsz = mMrkSz/2;
float dmsz = mMrkSz-hmsz;
PIGrCoord x[11],y[11];
int k;
PILineAtt clatt;

if (mMrk == PI_DotMarker)
  XDrawPoint(mDisp, mWId, DefGC(), (int)x0, (int)y0);

else  {
  clatt = mLAtt;
  SelLine(PI_ThinLine);
  switch (mMrk) {
    case  PI_PlusMarker :
      DrawLine((float)x0-hmsz, y0, (float)x0+dmsz, y0);
      DrawLine(x0, (float)y0-hmsz, x0, (float)y0+dmsz);
      break;
    case  PI_CrossMarker :
      DrawLine((float)x0-hmsz, (float)y0-hmsz, (float)x0+dmsz, (float)y0+dmsz);
      DrawLine((float)x0-hmsz, (float)y0+dmsz, (float)x0+dmsz, (float)y0-hmsz);
      break;  
    case PI_CircleMarker :
      DrawCircle(x0, y0, hmsz);
      break;
    case PI_FCircleMarker :
      DrawFCircle(x0, y0, hmsz);
      break;
    case PI_BoxMarker :
      DrawBox((float)x0-hmsz, (float)y0-hmsz, mMrkSz, mMrkSz);
      break;
    case PI_FBoxMarker :
      DrawFBox((float)x0-hmsz, (float)y0-hmsz, mMrkSz, mMrkSz);
      break;
    case  PI_TriangleMarker :
      x[1] = mMrkSz; y[1] = 0; x[2] = -hmsz; y[2] = -mMrkSz; 
      x[3] = -dmsz; y[3] = +mMrkSz; x[0] = (float)x0-hmsz; y[0] = (float)y0+hmsz;  
      DrawPolygon(x, y, 4);
      break;
    case  PI_FTriangleMarker :
      x[1] = mMrkSz; y[1] = 0; x[2] = -hmsz; y[2] = -mMrkSz; 
      x[3] = -dmsz; y[3] = +mMrkSz; x[0] = (float)x0-hmsz; y[0] = (float)y0+hmsz;  
      DrawFPolygon(x, y, 4);
      break;
    case  PI_StarMarker :
    case  PI_FStarMarker :
      for(k=0; k<10; k++) {
        x[k] = (int)(starcoordx[k]*(float)mMrkSz+(float)x0+0.5);
        y[k] = (int)(starcoordy[k]*(float)mMrkSz+(float)y0+0.5);
        }
      x[10] = x[0];   y[10] = y[0];
      if (mMrk == PI_StarMarker)  DrawPolygon(x, y, 11, false);
      else DrawFPolygon(x, y, 11, false);
      break;
    default :
      XDrawPoint(mDisp, mWId, DefGC(), x0, y0);
      break;
    }
  SelLine(clatt);
  }

return;
}

/* --Methode-- */
void PIGraphicX::DrawMarkers(PIGrCoord *x, PIGrCoord *y, int n)
{
int i;
if (n <= 0)  return;
if (mMrk == PI_DotMarker)
  {
  XPoint multipoint[NMXXPOINTS];
  XPoint *pxp;
  if (n > NMXXPOINTS)  pxp = new XPoint[n];
  else pxp = multipoint;
  for(i=0; i<n; i++)  { pxp[i].x = x[i];  pxp[i].y = y[i]; } 
  XDrawPoints(mDisp, mWId, DefGC(), pxp, n, CoordModeOrigin);
  if (n > NMXXPOINTS)  delete[] pxp;  
  }
else for(i=0; i<n; i++) DrawMarker(x[i], y[i]);

return;
}


/* --Methode-- */
void PIGraphicX::DrawPixmap(PIGrCoord x, PIGrCoord y, unsigned char *pix, 
                            int sx, int sy, PIColorMap* cmap)
{
Window xw;
Display * mdsp;
int scr;
int depth;
int pad;
int i,j;
XImage * ximg;

if ( (sx < 1) || (sy < 1) )  return;
if ((pix == NULL) || (cmap == NULL)) return; 

  
xw = mWId;
mdsp = PIXDisplay();
scr = PIXScreen();

depth = DefaultDepth(mdsp,scr);
pad = (depth > 8) ? 32 : 8;
ximg = XCreateImage (mdsp,DefaultVisual(mdsp,scr),
                     depth,ZPixmap,0,NULL, sx, sy, pad,0);
if (ximg == NULL)  return;
ximg->data = new char [sy*ximg->bytes_per_line];
if (ximg->data == NULL)  
  { XFree(ximg); return; }

for(j=0; j<sy; j++)
  for(i=0; i<sx; i++)
    { XPutPixel(ximg, i, j, cmap->Color(*pix) );  pix++; }

XPutImage(mdsp, xw, dpxgc, ximg, 0, 0, (int)x, (int)y, sx, sy);

delete[] ximg->data;
XFree(ximg); 
return;
}



/* --Methode-- */
void PIGraphicX::SelForeground(PIColors col)
{
if (col == mFCol)  return;
if ( (col < 0) || (col >= NMAXCOL))  return;
XSetForeground(mDisp, DefGC(), colpix[col]); 
mFCol = col;  
return;
}

/* --Methode-- */
void PIGraphicX::SelBackground(PIColors col)
{
if (col == mBCol)  return;
if ( (col < 0) || (col >= NMAXCOL))  return;
XSetBackground(mDisp, DefGC(), colpix[col]); 
mBCol = col;  
return;
}

/* --Methode-- */
void PIGraphicX::SelForeground(PIColorMap& cmap, int cid)
{
SelectFCol(cmap.Color(cid));
}

/* --Methode-- */
void PIGraphicX::SelBackground(PIColorMap& cmap, int cid)
{
SelectBCol(cmap.Color(cid));
}

/* --Methode-- */
void PIGraphicX::SelGOMode(PIGOMode mod)
{
if (mod == mGOm)  return;
switch (mod)
  {
  case PI_GOCopy :
    XSetFunction(mDisp, DefGC(), GXcopy);
    mGOm = mod;
    break;
  case PI_GOXOR :
    XSetFunction(mDisp, DefGC(), GXxor);
    mGOm = mod;
    break;
  case PI_GOInvert :
    XSetFunction(mDisp, DefGC(), GXinvert);
    mGOm = mod;
    break;
  }
return;
}


/* --Methode-- */
void PIGraphicX::SelFont(PIFont & fnt)
{
if (myFont == fnt)  return;
myFont = fnt;
XSetFont(mDisp, DefGC(), myFont.GetXFontId());
}

/* --Methode-- */
void PIGraphicX::SelFont(PIFontSize sz, PIFontAtt att)
{
PIFont fnt(myFont.GetFontName());
fnt.SetFontAtt(att);
fnt.SetFontSz(sz);
SelFont(fnt);
}

/* --Methode-- */
void PIGraphicX::SelFontSzPt(int npt, PIFontAtt att)
{
PIFont fnt(npt, myFont.GetFontName(), att);
SelFont(fnt);
}



/* --Methode-- */
void PIGraphicX::SelLine(PILineAtt att)
{
unsigned int lt=0;
int lstyle=LineSolid;
char dash[2]= {3,3};   

if (att == mLAtt)  return;

switch (att)
  {
  case PI_NormalLine :
    lt = 2;
    lstyle = LineSolid;
    break;
  case PI_ThickLine :
    lt = 4;
    lstyle = LineSolid;
    break;
  case  PI_ThinLine :
    lt = 0;
    lstyle = LineSolid;
    break;

  case PI_DashedLine :
    lt = 2;
    lstyle = LineOnOffDash;
    dash[0] = dash[1] = 6;  
    break;
  case PI_ThickDashedLine :
    lt = 4;
    lstyle = LineOnOffDash;
    dash[0] = dash[1] = 6;  
    break;
  case  PI_ThinDashedLine :
    lt = 0;
    lstyle = LineOnOffDash;
    dash[0] = dash[1] = 6;  
    break;

  case PI_DottedLine :
    lt = 2;
    lstyle = LineOnOffDash;
    dash[0] = 2; dash[1] = 6;  
    break;
  case PI_ThickDottedLine :
    lt = 4;
    lstyle = LineOnOffDash;
    dash[0] = 2; dash[1] = 6;  
    break;
  case  PI_ThinDottedLine :
    lt = 0;
    lstyle = LineOnOffDash;
    dash[0] = 2; dash[1] = 6;  
    break;

  default:
    lt = 0;
    lstyle=LineSolid;
    break;
  }

if (lstyle != LineSolid) 
  XSetDashes( mDisp, DefGC(), 0, dash, 2);
  
XSetLineAttributes(mDisp, DefGC(), lt, lstyle, CapButt, JoinMiter);
mLAtt = att;
return;
}


/* --Methode-- */
void PIGraphicX::SelMarker(int msz, PIMarker mrk)
{
if (msz > 1)  { mMrk = mrk;  mMrkSz = msz; }
else  { mMrk = PI_DotMarker;  mMrkSz = 1; }
return;
}


/* --Methode-- */
void PIGraphicX::SetClipRectangle(PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy)
{
XRectangle xr;
xr.x = x0;  xr.y = y0;
xr.width = dx;  xr.height = dy;
XSetClipRectangles(mDisp, DefGC(), 0, 0, &xr, 1, Unsorted);
XSetClipRectangles(mDisp, dpxgc, 0, 0, &xr, 1, Unsorted);
return;
}

/* --Methode-- */
void PIGraphicX::ClearClipRectangle()
{ 
XSetClipMask(mDisp, DefGC(), None);
XSetClipMask(mDisp, dpxgc, None);
return;
}

/* --Methode-- */
PIColors  PIGraphicX::GetForeground() 
{
return (mFCol);
}

/* --Methode-- */
PIColors  PIGraphicX::GetBackground() 
{
return (mBCol);
}


/* --Methode-- */
PIGOMode   PIGraphicX::GetGOMode()
{
return (mGOm);
}

/* --Methode-- */
PIFontAtt  PIGraphicX::GetFontAtt()
{
return (mFAtt);
}

/* --Methode-- */
int        PIGraphicX::GetFontSize()
{
return (mFSize);
}

/* --Methode-- */
PILineAtt  PIGraphicX::GetLineAtt()
{
return (mLAtt);
}

/* --Methode-- */
PIMarker   PIGraphicX::GetMarker()
{
return (mMrk);
}

/* --Methode-- */
int        PIGraphicX::GetMarkerSize()
{
return (mMrkSz);
}


/* --Methode-- */
void PIGraphicX::SaveGraphicAtt()
{  
// Pour optimier l'implementation de PIBaseWdgGen
sFCol = mFCol;    sBCol = mBCol;
sGOm = mGOm;
sFont = myFont;   
sMrk = mMrk;   sMrkSz = mMrkSz;
sFCfMap = mFCfMap; sBCfMap = mBCfMap; 
return;
}

/* --Methode-- */
void PIGraphicX::RestoreGraphicAtt()
{
  if (sFCol != PI_ColorFromMap) SelForeground(sFCol);
  else SelectFCol(sFCfMap);
  if (sBCol != PI_ColorFromMap) SelBackground(sBCol);
  else SelectBCol(sBCfMap);
  SelGOMode(sGOm);
  SelFont(sFont);
  SelLine(sLAtt);
  SelMarker(sMrkSz, sMrk);
  return;
}


/* --Methode-- */
unsigned long PIGraphicX::GetPixelValueforColor(PIColors col)
{
if ( (col < 0) || (col >= NMAXCOL))  return(0);
GlInit();
return(colpix[col]); 
}


static bool fggrcx = false ;  // Flag init done


/* --Methode-- */
void PIGraphicX::GlInit()
{
if (fggrcx)  return;
fggrcx = true;

Display *mdsp;
int scr;
XColor exact,mycol;
Colormap  cmap;

mdsp = PIXDisplay();
scr = XDefaultScreen(mdsp);

/*  Les couleurs  */
cmap = XDefaultColormap (mdsp, scr);

for(int i=0; i<NMAXCOL; i++)  colpix[i] = XWhitePixel(mdsp, scr);
colpix[PI_Black] = XBlackPixel(mdsp, scr);
colpix[PI_White] = XWhitePixel(mdsp, scr);
colpix[PI_ColorAllBits0] = 0;
colpix[PI_ColorAllBits1] = ~colpix[PI_ColorAllBits0];
if ( XAllocNamedColor (mdsp, cmap, "LightGray", &mycol, &exact) )
  colpix[PI_Grey] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "red", &mycol, &exact) )
  colpix[PI_Red] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "blue", &mycol, &exact) )
  colpix[PI_Blue] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "green", &mycol, &exact) )
  colpix[PI_Green] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "yellow", &mycol, &exact) )
  colpix[PI_Yellow] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "magenta", &mycol, &exact) )
  colpix[PI_Magenta] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "cyan", &mycol, &exact) )
  colpix[PI_Cyan] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "turquoise", &mycol, &exact) )
  colpix[PI_Turquoise] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "NavyBlue", &mycol, &exact) )
  colpix[PI_NavyBlue] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "orange", &mycol, &exact) )
  colpix[PI_Orange] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "sienna", &mycol, &exact) )
  colpix[PI_SiennaRed] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "purple", &mycol, &exact) )
  colpix[PI_Purple] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "LimeGreen", &mycol, &exact) )
  colpix[PI_LimeGreen] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "gold", &mycol, &exact) )
  colpix[PI_Gold] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "violet", &mycol, &exact) )
  colpix[PI_Violet] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "VioletRed", &mycol, &exact) )
  colpix[PI_VioletRed] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "BlueViolet", &mycol, &exact) )
  colpix[PI_BlueViolet] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "DarkViolet", &mycol, &exact) )
  colpix[PI_DarkViolet] = mycol.pixel;


/*  le GC pour DrawPixmap  */
XGCValues  xgv;
xgv.function = GXcopy;
xgv.plane_mask = ~0;
dpxgc = XCreateGC(mdsp, DefaultRootWindow(mdsp), GCFunction | GCPlaneMask, &xgv);

/* Coordonnees pour une etoile a 5 branches */
double pio5 = M_PI/2.5;  
double pio52 = pio5/2.;
double cpi2 = M_PI/2.-pio5;  
double re = 1.2;  // Rayon externe
double ri = 0.5; //  rayon interne pour rext=1.2
for(int k=0; k<5; k++) {
  starcoordx[2*k] = cos(k*pio5+cpi2)*re;
  starcoordy[2*k] = -sin(k*pio5+cpi2)*re;
  starcoordx[2*k+1] = cos(k*pio5+pio52+cpi2)*ri;
  starcoordy[2*k+1] = -sin(k*pio5+pio52+cpi2)*ri;
  }

}




