SPLINE.cpp



//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
#include <owl\owlpch.h>
#include <owl\applicat.h>
#include <owl\framewin.h>
#include <owl\dc.h>
#include <owl\inputdia.h>
#include <owl\opensave.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <classlib\arrays.h>
#include "spline.rc"

struct puntos
{
	float x;			//  coorde		valor(x)
	float y;            		//  nadas		valor(y)
	float t;     			//  Angulo de abertura
	struct puntos *sig;
};

struct puntos *inicio;		// Apuntador al primer nodo
int n_puntos = 0;		// Puntos seleccionados con el raton
int limpiar = 0;			// Bandera para limpiar la ventana

class TMyWindow : public TWindow {
  public:
	 TMyWindow(TWindow *parent = 0);
	 int QueryPen() const { return PenSize; }
	 int QueryPen(int penSize);
	 void traza(void);
	 float hermite(int, int, int, int, float);
	 int distancia(struct puntos*,float,float);
	 void marca(int,int);

  protected:
	 int PenSize;
	 TOpenSaveDialog::TData
				  *FileData;
	 BOOL IsDirty, IsNewFile;

	 int GetPenSize();

	 // Override member function of TWindow
	 BOOL CanClose();

	 // Message response functions
	 void EvLButtonDown(UINT, TPoint&);
	 void EvRButtonDown(UINT, TPoint&);
	 void CmSalir();
	 void CmPenSize();
	 void CmAbout();

	 DECLARE_RESPONSE_TABLE(TMyWindow);
};

int TMyWindow::QueryPen(int penSize)
{
  if (penSize < 0)
	 PenSize = 1;
  else if (penSize > 0)
	 PenSize = penSize;
  return PenSize;
}

DEFINE_RESPONSE_TABLE1(TMyWindow, TWindow)
  EV_WM_LBUTTONDOWN,
  EV_WM_RBUTTONDOWN,
  EV_WM_MOUSEMOVE,
  EV_WM_LBUTTONUP,
  EV_COMMAND(CM_FILEEND, CmSalir),
  EV_COMMAND(CM_ABOUT, CmAbout),
  EV_COMMAND(CM_PENSIZE, CmPenSize),
END_RESPONSE_TABLE;

TMyWindow::TMyWindow(TWindow *parent)
{
  Init(parent, 0, 0);
  IsNewFile = TRUE;
  IsDirty = FALSE;
  FileData = new TOpenSaveDialog::TData(OFN_HIDEREADONLY|OFN_FILEMUSTEXIST,
													 "Point Files (*.PT8)|*.pt8|", 0, "",
													 "PT8");
}

BOOL TMyWindow::CanClose()
{ return TRUE; }

void TMyWindow::EvLButtonDown(UINT, TPoint& point)
{
  struct puntos *nodo = NULL;
  struct puntos *act = NULL;
  struct puntos *ant = NULL;
  char s[16];
  TClientDC dc(*this);

		  n_puntos++;
		  wsprintf(s, "%d",n_puntos);
		  dc.TextOut(point, s, strlen(s));
		  marca(point.x, point.y);

		  nodo = (struct puntos *)malloc(sizeof(struct puntos));
		  nodo->x = point.x;
		  nodo->y = point.y;
		  nodo->t = 0; // nodo->t = GetPenSize();
		  nodo->sig = NULL;

		  if(!inicio) inicio = nodo;
		  else
		  {
			  act = inicio;
			  while(act) { ant = act; act = act->sig; }
			  ant->sig = nodo;
		  }
}

void TMyWindow::EvRButtonDown(UINT, TPoint&)
{
  if (limpiar)
  {
	  Invalidate();		// limpia ventana
	  limpiar = 0;
	  inicio = NULL;
	  n_puntos = 0;
  }
  else
  {
	  traza();
	  limpiar = 1;
  }
}

void TMyWindow::CmSalir()
{	exit(1); }

void TMyWindow::CmPenSize()
{ ; }

int TMyWindow::GetPenSize()
{
  char inputText[6];
  int angulo = 1;

								"Introduzca la pendiente:",
								inputText,
								sizeof(inputText))).Execute() == IDOK) {
	 angulo = atoi(inputText);

	 if (angulo < 0)
		angulo = 360 + angulo;
  }
  return angulo;
}

void TMyWindow::CmAbout()
{ TDialog(this, IDD_ABOUT).Execute(); }

class TMyApp : public TApplication {
  public:
	 TMyApp() : TApplication() {}

	 void InitMainWindow()
	 {
		GetMainWindow()->AssignMenu("COMMANDS");
	 }
};

void TMyWindow::traza(void)
{
	struct puntos *act  = inicio;
	struct puntos *pk0  = NULL;
	struct puntos *pk1  = NULL;
	struct puntos *pk2  = NULL;
	struct puntos *pk3  = NULL;
	char error[40];
	float u, x, y;
	TClientDC dc(*this);

  if(n_puntos > 3)			// existen al menos 4 puntos
  {
	  while(act)				// mientras haya puntos
	  {
			  pk0 = act;
			  if(pk0->sig) pk1 = pk0->sig; else break;
			  if(pk1->sig) pk2 = pk1->sig; else break;
			  if(pk2->sig) pk3 = pk2->sig; else break;

			  for(u=0; u<=1; u += 0.001)
			  {
				  x = hermite(pk0->x, pk1->x, pk2->x, pk3->x, u);
				  y = hermite(pk0->y, pk1->y, pk2->y, pk3->y, u);

				  SetPixel(dc, x, y, 8);			// pone un punto en la ventana
			  }
		  act = act->sig;
	  }
  }
  else
  {
	  wsprintf(error, "- %s -","No hay puntos suficientes");
	  dc.TextOut(10,10, error, strlen(error));
  }
}


float TMyWindow::hermite(int pk0, int pk1, int pk2, int pk3, float u)
{
	float u2, u3, s = 0.5, valor;

	u2 = u*u;
	u3 = u*u*u;

	valor = pk0 * (-s*u3 + 2*s*u2 - s*u) +
			  pk1 * ( (2-s)*u3 + (s-3)*u2 + 1) +
			  pk2  *( (s-2)*u3 +(3-2*s)*u2 + s*u) +
			  pk3 * (s*u3 - s*u2);
	return valor;
}

void TMyWindow::marca(int x, int y)
{
	TClientDC dc(*this);
	int x1, y1;

	for(x1=x-5;x1<=x+5;x1++) SetPixel(dc, x1, y, 8);
	for(y1=y-5;y1<=y+5;y1++) SetPixel(dc, x, y1, 8);
}

int OwlMain(int /*argc*/, char* /*argv*/ [])
{
  inicio = NULL;
  TMyApp().Run();
  return 1;
}