/*
** (c) 1996-2000 The Regents of the University of California (through
** E.O. Lawrence Berkeley National Laboratory), subject to approval by
** the U.S. Department of Energy.  Your use of this software is under
** license -- the license agreement is attached and included in the
** directory as license.txt or you may contact Berkeley Lab's Technology
** Transfer Department at TTD@lbl.gov.  NOTICE OF U.S. GOVERNMENT RIGHTS.
** The Software was developed under funding from the U.S. Government
** which consequently retains certain rights as follows: the
** U.S. Government has been granted for itself and others acting on its
** behalf a paid-up, nonexclusive, irrevocable, worldwide license in the
** Software to reproduce, prepare derivative works, and perform publicly
** and display publicly.  Beginning five (5) years after the date
** permission to assert copyright is obtained from the U.S. Department of
** Energy, and subject to any subsequent five (5) year renewals, the
** U.S. Government is granted for itself and others acting on its behalf
** a paid-up, nonexclusive, irrevocable, worldwide license in the
** Software to reproduce, prepare derivative works, distribute copies to
** the public, perform publicly and display publicly, and to permit
** others to do so.
*/


//
// $Id: ProjectionPicture.H,v 1.22 2002/12/10 20:12:23 vince Exp $
//

// ---------------------------------------------------------------
// ProjectionPicture.H
// ---------------------------------------------------------------
#ifndef _PROJECTIONPICTURE_H_
#define _PROJECTIONPICTURE_H_

#include <Xm/Xm.h>
#undef index

#include "AmrPicture.H" 
#include "ViewTransform.H" 
#include "Palette.H"

#ifdef BL_VOLUMERENDER
#include "VolRender.H" 
#endif

class PltApp;

// represents data points in physical space that connect lines to other points
class RealPoint {
  public:
    RealPoint() { component[0] = component[1] = component[2] = 0.0; }
    Real component[3];
    RealPoint(Real r1, Real r2, Real r3) {
      component[0] = r1; 
      component[1] = r2;
      component[2] = r3;
    }
};

// represents box points in screen space with color values
class TransPoint {
  public:
    TransPoint() { x = y = 0; }
    int x, y;
    TransPoint( int n1, int n2) { x = n1; y = n2; }
};


class RealBox {
  public:
    RealBox();
    ~RealBox() { }
    RealBox(const Box &theBox);
    RealPoint vertices[8];
};

class TransBox {
  public:
    TransBox();
    ~TransBox() { }
    void Draw(Display *display, Window window, GC gc);
    TransPoint vertices[8];
};

class RealSlice {
  public:
    RealSlice();
    ~RealSlice() {}
    RealSlice(int count, int slice, const Box &worldBox);
    RealSlice(RealPoint p1, RealPoint p2, RealPoint p3, RealPoint p4);
    void ChangeSlice(int NewSlice);
    RealPoint edges[4];
    int dirOfFreedom; // [0, 2]
};

class TransSlice {
  public:
    TransSlice();
    ~TransSlice() {}
    TransSlice(TransPoint p1, TransPoint p2, TransPoint p3, TransPoint p4);
    void Draw(Display *display, Window window, GC gc);
    TransPoint edges[4];
};

//-----------------------------------------------------------------

class ProjectionPicture {
public:
  ProjectionPicture(PltApp *, ViewTransform *, Palette *, Widget, int, int);
  
  ~ProjectionPicture();
  
#ifdef BL_VOLUMERENDER
  VolRender *GetVolRenderPtr() const { return volRender; }
#endif
  void	MakeBoxes();
  void MakeSlices();
  void	MakePicture();
  void	DrawBoxesIntoDrawable(const Drawable &drawable,
                              int iFromLevel, int iToLevel);
  void	DrawBoxes(int iFromLevel, int iToLevel);
  XImage *DrawBoxesIntoPixmap(int iFromLevel, int iToLevel);
  void	DrawPicture();
  void	LabelAxes();
  void	ToggleShowSubCut();
  void	SetSubCut(const Box &newbox);
  void	SetDrawingAreaDimensions(int w, int h); // called when resized 
  void SetDrawingArea(Widget drawhere) { drawingArea = drawhere; }
  XImage *GetPictureXImage() const { return PPXImage; }
  int ImageSizeH() const { return daWidth; }
  int ImageSizeV() const { return daHeight; }
  void ChangeSlice(int Dir, int newSlice);
  Real LongestBoxSide() const { return longestBoxSide; }
  
  
private:
  enum { NVERTICIES = 8 };
  
  Widget	  drawingArea;
  AmrPicture     *amrPicturePtr;
  ViewTransform  *viewTransformPtr;
  Array<Array<RealBox> > boxReal;
  Array<Array<TransBox> > boxTrans;
  Real longestBoxSide;
  
  RealBox realBoundingBox;
  TransBox transBoundingBox;
  
  RealBox realSubCutBox;
  TransBox transSubCutBox;
  
  RealSlice realSlice[3];
  TransSlice transSlice[3];
  
  Array<int> boxPoints;
  Array<int> boxColors;
  int subCutColor, sliceColor, daWidth, daHeight;
  bool showSubCut, pixCreated;
  int  minDrawnLevel, maxDrawnLevel, maxDataLevel;
  Real xcenter, ycenter, zcenter;
  Pixmap pixMap;
  Palette *palettePtr;
  unsigned char *imageData, *volpackImageData;
  XImage *PPXImage;
  Array<Box> theDomain;
  char buffer[BUFSIZ];
  PltApp *pltAppPtr;
  Real scale[3];
  Real longestWindowLength, shortestWindowLength;
  int  longestBoxSideDir;
  int  nDenRampPts, nGradRampPts, nShadeRampPts;
  int  maxDenRampPts, maxGradRampPts, maxShadeRampPts;
  unsigned char	volumeBoxColor;
#ifdef BL_VOLUMERENDER
  VolRender *volRender;
#endif
  void MakeAuxiliaries();
  void MakeBoundingBox();
  void MakeSubCutBox();
  void DrawAuxiliaries(const Drawable &drawable);
  void DrawSlices(const Drawable &drawable);
  void LoadSlices(const Box &surroundingBox);
  // converts a Box to eight BoxRealPoints at the specified level
  void AddBox(const Box &theBox, int index, int level);
  void TransformBoxPoints(int iLevel, int iBoxIndex);

};

//--------------------------------------------------------------------

#endif
