/*
   File:        gpro.c
   Author:      Andrew W. Moore
   Created:     Sat Sep 12 19:52:11 EDT 1992
   Description: Evil Stuff defining 2d graphics view of kd space

   Copyright (C) 1992, Andrew W. Moore
*/

#include <stdio.h>
#include <math.h>
#include "ambs.h"      /* Very basic operations */
#include "amar.h"      /* Obvious operations on 1-d arrays */
#include "amgr.h"      /* Basic (0,512)x(0,512) Graphics window */
#include "maxdim.h"    /* The MAX_DIM declaration */
#include "gpro.h"      /* Graphics projections kd->2d space */

float f2a(ax,v)
axis *ax;
float v;
{
  return( ax -> glo + (v-ax->lo) * (ax->ghi - ax->glo) / (ax->hi - ax->lo) );
}

float a2f(ax,v)
axis *ax;
float v;
{
  return( ax -> lo + (v-ax->glo) * (ax->hi - ax->lo) / (ax->ghi - ax->glo));
}

void gp_clear(gp)
gproj *gp;
{
  ag_on("");
}

void gp_draw_dot(gp,x,y)
gproj *gp;
float x,y;
{
  ag_dot(f2a(&gp->x,x),f2a(&gp->y,y));
}

void gp_draw_little_square(gp,x,y)
gproj *gp;
float x,y;
{
  float ax = f2a(&gp->x,x);
  float ay = f2a(&gp->y,y);
  float d = 1.6;
  ag_rectangle(ax-d,ay-d,ax+d,ay+d);
}

void gp_draw_string(gp,x,y,s)
gproj *gp;
float x,y;
char *s;
{
  ag_print(f2a(&gp->x,x),f2a(&gp->y,y),s);
}

void gp_draw_line(gp,x,y,x2,y2)
gproj *gp;
float x,y,x2,y2;
{
  ag_line(f2a(&gp->x,x),f2a(&gp->y,y),f2a(&gp->x,x2),f2a(&gp->y,y2));
}

void gp_draw_box(gp,x,y,x2,y2)
gproj *gp;
float x,y,x2,y2;
{
  ag_box(f2a(&gp->x,x),f2a(&gp->y,y),f2a(&gp->x,x2),f2a(&gp->y,y2));
}

void gp_draw_rectangle(gp,x,y,x2,y2)
gproj *gp;
float x,y,x2,y2;
{
  ag_rectangle(f2a(&gp->x,x),f2a(&gp->y,y),f2a(&gp->x,x2),f2a(&gp->y,y2));
}

void gp_print_data(gp)
gproj *gp;
{
  char buff[100];
  sprintf(buff,"x=[%g..%g] y=[%g..%g]",gp->x.lo,gp->x.hi,gp->y.lo,gp->y.hi);
  gp_draw_string(gp,gp->x.hi * 0.9 + gp->x.lo * 0.1,gp->y.lo,buff);
  if ( gp->size > 2 )
  {
    int i;
    char temp_buff[100];
    sprintf(buff,"(");
    for ( i = 0 ; i < gp->size ; i++ )
    {
      char *next = (i == gp->size-1) ? ")" : ",";
      sprintf(temp_buff,"%s",buff);
      if ( i == gp->x.comp )
        sprintf(buff,"%sx%s",temp_buff,next);
      else if ( i == gp->y.comp )
        sprintf(buff,"%sy%s",temp_buff,next);
      else
        sprintf(buff,"%s%g%s",temp_buff,gp->base[i],next);
    }
    gp_draw_string(gp,gp->x.hi * 0.8 + gp->x.lo * 0.2,gp->y.lo,buff);
  }
}

int gp_use_mouse(gp,farr)
gproj *gp;
float *farr;
{
  float x,y;
  int button = ag_get_xy(&x,&y);
  copy_floats(gp->base,farr,gp->size);
  farr[gp->x.comp] = a2f(&gp->x,x);
  farr[gp->y.comp] = a2f(&gp->y,y);
  return(button);
}

void axis_from_m_and_s(ax,middle,scales,comp)
axis *ax;
float *middle;
float *scales;
int comp;
{
  ax->lo = middle[comp] - scales[comp];
  ax->hi = middle[comp] + scales[comp];
  ax->glo = 0.0;      /* The whole window */
  ax->ghi = 512.0;    /* The whole window */
  ax->comp = comp;
}

void gproj_from_m_and_s(gp,middle,scales,dim,xcomp,ycomp)
gproj *gp;
float *middle;
float *scales;
int dim;
int xcomp;
int ycomp;
{
  if ( dim < 2 )
    my_error("gproj_from_m_and_s(): dimension must be 2 or more");
  else
  {
    gp -> size = dim;
    copy_floats(middle,gp->base,dim);
    axis_from_m_and_s(&gp->x,middle,scales,xcomp);
    axis_from_m_and_s(&gp->y,middle,scales,ycomp);
  }
}

void gp_draw_floats_dot(gp,farr)
gproj *gp;
float *farr;
{
  gp_draw_dot(gp,farr[gp->x.comp],farr[gp->y.comp]);
}

void gp_draw_floats_little_square(gp,farr)
gproj *gp;
float *farr;
{
  gp_draw_little_square(gp,farr[gp->x.comp],farr[gp->y.comp]);
}

void gp_draw_circle(gp,x,y,pix_radius)
gproj *gp;
float x,y;
float pix_radius;
{
  ag_circle(f2a(&gp->x,x),f2a(&gp->y,y),pix_radius);
}

void gp_draw_disc(gp,x,y,pix_radius)
gproj *gp;
float x,y;
float pix_radius;
{
  ag_disc(f2a(&gp->x,x),f2a(&gp->y,y),pix_radius);
}

void gp_draw_floats_circle(gp,farr,pix_radius)
gproj *gp;
float *farr;
float pix_radius;
{
  gp_draw_circle(gp,farr[gp->x.comp],farr[gp->y.comp],pix_radius);
}

void gp_draw_floats_disc(gp,farr,pix_radius)
gproj *gp;
float *farr;
float pix_radius;
{
  gp_draw_disc(gp,farr[gp->x.comp],farr[gp->y.comp],pix_radius);
}

void gp_draw_floats_line(gp,farr1,farr2)
gproj *gp;
float *farr1,*farr2;
{
  gp_draw_line(gp,farr1[gp->x.comp],farr1[gp->y.comp],
                  farr2[gp->x.comp],farr2[gp->y.comp]
              );
}

