[BACK]Return to smoothing.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib2 / asir2000 / plot

File: [local] / OpenXM_contrib2 / asir2000 / plot / smoothing.c (download)

Revision 1.2, Sun Oct 15 10:58:11 2000 UTC (23 years, 7 months ago) by takayama
Branch: MAIN
Changes since 1.1: +68 -2 lines

Added coordinate axis for Postscript output for ifplot.

/* $OpenXM: OpenXM_contrib2/asir2000/plot/smoothing.c,v 1.2 2000/10/15 10:58:11 takayama Exp $ */
#include "ca.h"
#include "parse.h"
#include "ox.h"
#include "ifplot.h"
#include "cursor.h"

#define MAG 1
#define PRINT_XOFFSET   100
#define PRINT_YOFFSET   100

struct polyLine {
  int numberOfSegments;
  int limit;
  int *x;
  int *y;
};

static FILE *Fp = NULL;

static void *gcmalloc(int a);
static struct polyLine *polyLine_new(void);
static struct polyLine *polyLine_addNewSegment(struct polyLine *pl,
											   int x,int y);
static int polyLine_lastY(struct polyLine *pl);
static void polyLine_outputPS(struct polyLine *pl);
static void polyLine_outputProlog(int xmin, int ymin, int xmax, int ymax);
static void polyLine_outputEpilog(void);
static void polyLine_error(char *s);
#define translateX(x)  (x*MAG+PRINT_XOFFSET)
#define translateY(y)  (y*MAG+PRINT_YOFFSET)
/* #define translateY(y) ((Ysize-y)*MAG+PRINT_YOFFSET) */
#define IS_DOT    != 0
#define IS_POLYLINE  > -1
#define YES 1
#define NO  0


static int Xsize = 0;
static int Ysize = 0;
static int updatePolyLine(struct polyLine *pl[], int plSize,
				   int prev[], int Curr[], int x);

static void polyLine_outputPS_dashed_line(int x0,int y0,int x1,int y1);
static int polyLine_pline(struct canvas *can);


static void *gcmalloc(a)  {
  void *m;
  /* BUG:  interruption must be locked. */
  m = (void *) GC_malloc(a);
  if (m == NULL) polyLine_error("no memory");
  return(m);
}

#define MINIMAL_POLYLINE_SIZE  10
static struct polyLine *polyLine_new_with_size(int size) {
  struct polyLine *pl;
  pl = (struct polyLine *)gcmalloc(sizeof(struct polyLine));
  pl-> limit = (size > 0? size: 1);
  pl-> numberOfSegments = 0;
  pl->x = (int *)gcmalloc(sizeof(int)*(pl->limit));
  pl->y = (int *)gcmalloc(sizeof(int)*(pl->limit));
  return(pl);
}

static struct polyLine *polyLine_new(void) {
  return( polyLine_new_with_size(MINIMAL_POLYLINE_SIZE));
}

static struct polyLine *polyLine_addNewSegment(struct polyLine *pl,
												int x,int y) {
  int n,limit,i;
  struct polyLine *new_pl;
  limit = pl->limit;
  n = pl->numberOfSegments;
  if (n >= limit) {
	new_pl = polyLine_new_with_size( 2*limit );
	new_pl -> numberOfSegments = pl->numberOfSegments;
	for (i=0; i<pl->numberOfSegments; i++) {
	  new_pl->x[i] = pl->x[i];
	  new_pl->y[i] = pl->y[i];
	}
	pl = new_pl;
  }
  pl->numberOfSegments++;
  pl->x[n] = x;
  pl->y[n] = y;
  return(pl);
}

static int polyLine_lastY(struct polyLine *pl) {
  int n;
  n = pl->numberOfSegments;
  if (n == 0) {
	polyLine_error("polyLine_lastY:  empty polyLine.");
  }
  return(pl->y[n-1]);
}


static void polyLine_outputPS(struct polyLine *pl) {
  int n,i;
  n = pl->numberOfSegments;
  if (n == 1) {
	fprintf(Fp," %d %d ifplot_putpixel\n",translateX(pl->x[0]),translateY(pl->y[0]));
  }else if (n > 1) {
	fprintf(Fp," newpath ");
	for (i=0; i<n; i++) {
	  fprintf(Fp," %d %d ",translateX(pl->x[i]),translateY(pl->y[i]));
	  if (i==0) fprintf(Fp," moveto ");
	  else fprintf(Fp," lineto ");
	}
	fprintf(Fp," stroke\n");
  }
  fflush(Fp);
}
static void polyLine_outputProlog(int xmin, int ymin,int xmax, int ymax) {
  fprintf(Fp,"%%!PS-Adobe-1.0\n");
  fprintf(Fp,"%%%%BoundingBox: %d %d %d %d \n",
		  PRINT_XOFFSET+xmin*MAG,PRINT_YOFFSET+ymin*MAG,
		  PRINT_XOFFSET+xmax*MAG, PRINT_YOFFSET+ymax*MAG);
  fprintf(Fp,"%%%%Creator: This is generated by ifplot\n");
  fprintf(Fp,"%%%%Title: ifplot\n");
  fprintf(Fp,"%%%%EndComments: \n");
  fprintf(Fp,"/ifplot_putpixel {  \n");
  fprintf(Fp,"    /yyy 2 1 roll def /xxx 2 1 roll def \n");
  fprintf(Fp,"    gsave newpath xxx yyy .5 0 360 arc \n");
  fprintf(Fp,"    fill grestore \n");
  fprintf(Fp,"} def \n");
  fflush(Fp);
}
static void polyLine_outputEpilog(void) {
  fprintf(Fp,"showpage \n"); fflush(Fp);
}
static void polyLine_error(char *s) {
  fprintf(stderr,"Error in smoothing: %s\n",s);
  exit(-1);
}
static int updatePolyLine(struct polyLine *pl[], int plSize,
						  int prev[], int curr[],int x) {
  /*  1 <= y <= Ysize ,  curr[0], curr[Ysize+1]  = 0 ,  i=y .
	  prev = {-1, -1, -1, 0, 1, -1, 2, -1}  -1: no polyLine. 0:pl[0], 1:pl[1],
	  curr = {0,  1,  0,  1, 1, 1,  0, 0}    0: no dot, 1: dot.
  */
  /* Return Value:  plSize, pl, prev */
  int i;
  static int *prevHasNext = NULL;
  static struct polyLine **tmpPl = NULL;
  static struct polyLine **newPl = NULL;
  int tmpPlSize = 0;
  static int *tmpPrev = NULL;
  int newPlSize = 0;
  extern int Ysize;
  if (prevHasNext == NULL) prevHasNext = (int *)gcmalloc(sizeof(int)*(Ysize+2));
  if (tmpPl == NULL)
	tmpPl = (struct polyLine **)gcmalloc(sizeof(struct polyLine *)*(Ysize+2));
  if (newPl == NULL)
	newPl = (struct polyLine **)gcmalloc(sizeof(struct polyLine *)*(Ysize+2));
  if (tmpPrev == NULL) tmpPrev = (int *)gcmalloc(sizeof(int)*(Ysize+2));
  for (i=0; i<Ysize+2; i++) {
	prevHasNext[i] = NO; newPl[i] = NULL; tmpPl[i] = NULL;
	tmpPrev[i] = -1;
  }
  prev[0] = prev[Ysize+1] = -1;
  for (i=1; i <= Ysize; i++) {
	if (curr[i] IS_DOT) {
	  if (prev[i-1] IS_POLYLINE && !prevHasNext[i-1]) {
		pl[prev[i-1]] = polyLine_addNewSegment(pl[prev[i-1]],x,i);
		prevHasNext[i-1] = YES;
	  }else if (prev[i] IS_POLYLINE && !prevHasNext[i]) {
		pl[prev[i]] = polyLine_addNewSegment(pl[prev[i]],x,i);
		prevHasNext[i] = YES;
	  }else if (prev[i+1] IS_POLYLINE && !prevHasNext[i+1]) {
		pl[prev[i+1]] = polyLine_addNewSegment(pl[prev[i+1]],x,i);
		prevHasNext[i+1] = YES;
	  }else{
		newPl[newPlSize] = polyLine_new();
		newPl[newPlSize] = polyLine_addNewSegment(newPl[newPlSize],x,i);
		newPlSize++;
	  }
	}
  }
  for (i=1; i<=Ysize; i++) {
	if (prevHasNext[i] == NO && prev[i] IS_POLYLINE) {
	  polyLine_outputPS(pl[prev[i]]);
	}
  }

  /* generate new pl and new prev */
  tmpPlSize = 0; tmpPrev[0] = tmpPrev[Ysize+1] = -1;
  for (i = 1; i<=Ysize; i++) {
	if (prevHasNext[i] == YES) {
	  tmpPl[tmpPlSize] = pl[prev[i]];
	  tmpPrev[polyLine_lastY(pl[prev[i]])] = tmpPlSize;
	  tmpPlSize++;
	}
  }
  for (i=0; i<newPlSize; i++) {
	tmpPl[tmpPlSize] = newPl[i];
	tmpPrev[polyLine_lastY(newPl[i])] = tmpPlSize;
	tmpPlSize++;
  }

  /* copy and update for the next step.  */
  for (i=0; i< Ysize+2; i++) {
	prev[i] = tmpPrev[i];
  }
  for (i=0; i<tmpPlSize; i++) {
	pl[i] = tmpPl[i];
  }
  return(tmpPlSize);
}

/*
#define TEST_YSIZE 12
#define TEST_XSIZE 5
generatePS_from_image(FILE *fp) {
  int image_test[TEST_XSIZE][TEST_YSIZE] =
                          {{0,0,1,0,0,0,0,0,0,0,0,0},
                           {0,1,0,1,0,0,0,0,0,1,0,0},
                           {0,1,0,1,1,0,0,0,1,0,1,0},
                           {0,0,1,0,0,0,0,0,0,1,0,1},
                           {0,0,0,0,0,0,1,0,0,1,0,0}};
  struct polyLine **pl;
  int plSize = 0;
  int *prev;
  int *curr;
  int i,x,y;

  Xsize = TEST_XSIZE;
  Ysize = TEST_YSIZE;
  pl = (struct polyLine **)gcmalloc(sizeof(struct polyLine *)*(Ysize+2));
  prev = (int *)gcmalloc(sizeof(int)*(Ysize+2));
  curr = (int *)gcmalloc(sizeof(int)*(Ysize+2));
  Fp = fp;
  polyLine_outputProlog(0,0,Xsize,Ysize);
  for (i=0; i<= Ysize+1; i++) {
	prev[i] = -1;
  }
  for (x=0; x<Xsize; x++) {
	curr[0] = curr[Ysize+1] = 0;
	for (y=0; y<Ysize; y++) {
	  if (image_test[x][y]) curr[y+1]=1;
	  else curr[y+1] = 0;
	}
	plSize = updatePolyLine(pl,plSize,prev,curr,x);
  }
  for (y=0; y<Ysize+2; y++) {
	curr[y] = 0;
  }
  plSize = updatePolyLine(pl,plSize,prev,curr,Xsize);
  polyLine_outputEpilog();
}
main() {
  generatePS_from_image(stdout);
}

*/
static void polyLine_outputPS_dashed_line(int x0,int y0,int x1,int y1) {
  extern FILE *Fp;
  fprintf(Fp," gsave [3] 0 setdash newpath \n");
  fprintf(Fp," %d %d moveto %d %d lineto stroke \n",x0,y0,x1,y1);
  fprintf(Fp," stroke grestore \n");
}

#define D 5
static int polyLine_pline(can)
struct canvas *can;
{
	double w,w1,k,e,n;
	int x0,y0,x,y,xadj,yadj;
	char buf[BUFSIZ];
	double adjust_scale();

	if ( can->noaxis )
		return;

	xadj = yadj = 0;
	if ( (can->xmin < 0) && (can->xmax > 0) ) {
		x0 = (int)((can->width-1)*(-can->xmin/(can->xmax-can->xmin)));
		polyLine_outputPS_dashed_line(translateX(x0),translateY(0),
									  translateX(x0),translateY(can->height));
	} else if ( can->xmin >= 0 )
		x0 = 0;
	else
		x0 = can->width-1-D;
	if ( (can->ymin < 0) && (can->ymax > 0) ) {
		y0 = (int)((can->height-1)*(can->ymax/(can->ymax-can->ymin)));
		polyLine_outputPS_dashed_line(translateX(0),translateY(y0),
									  translateX(can->width),translateY(y0));
	} else if ( can->ymin >= 0 )
		y0 = can->height-1;
	else
		y0 = D;
	/* BUG:  not written yet a code for PS.
	w = can->xmax-can->xmin; 
	w1 = w * DEFAULTWIDTH/can->width;
	e = adjust_scale(EXP10(floor(log10(w1))),w1);
	for ( n = ceil(can->xmin/e); n*e<= can->xmax; n++ ) {
		x = (int)can->width*(n*e-can->xmin)/w;
		DRAWLINE(display,d,drawGC,x,y0,x,y0-D);
		sprintf(buf,"%g",n*e);
		DRAWSTRING(display,d,scaleGC,x+2,y0,buf,strlen(buf));
	}
	w = can->ymax-can->ymin;
	w1 = w * DEFAULTHEIGHT/can->height;
	e = adjust_scale(EXP10(floor(log10(w1))),w1);
	for ( n = ceil(can->ymin/e); n*e<= can->ymax; n++ ) {
		y = (int)can->height*(1-(n*e-can->ymin)/w);
		DRAWLINE(display,d,drawGC,x0,y,x0+D,y);
		sprintf(buf,"%g",n*e);
		if ( can->xmax <= 0 )
			xadj = TEXTWIDTH(sffs,buf,strlen(buf));
		DRAWSTRING(display,d,scaleGC,x0-xadj,y,buf,strlen(buf));
	}
	*/
}

generatePS_from_image(FILE *fp,XImage *image,int xsize, int ysize,
					  int color[],int colorSize,
					  struct canvas *can) {
  struct polyLine **pl;
  int plSize = 0;
  int *prev;
  int *curr;
  int i,x,y,c;

  Xsize = xsize;
  Ysize = ysize;
  pl = (struct polyLine **)gcmalloc(sizeof(struct polyLine *)*(Ysize+2));
  prev = (int *)gcmalloc(sizeof(int)*(Ysize+2));
  curr = (int *)gcmalloc(sizeof(int)*(Ysize+2));
  Fp = fp;
  polyLine_outputProlog(0,0,Xsize,Ysize);
  for (c=0; c<colorSize; c++) {
	/* Set color if necessary */
	for (i=0; i<= Ysize+1; i++) {
	  prev[i] = -1;
	}
	for (x=0; x<Xsize; x++) {
	  curr[0] = curr[Ysize+1] = 0;
	  for (y=0; y<Ysize; y++) {
		if ((int) XGetPixel(image,x,y) == color[c]) curr[y+1]=1;
		else curr[y+1] = 0;
	  }
	  plSize = updatePolyLine(pl,plSize,prev,curr,x);
	}
	for (y=0; y<Ysize+2; y++) {
	  curr[y] = 0;
	}
	plSize = updatePolyLine(pl,plSize,prev,curr,Xsize);
  }
  polyLine_pline(can);
  polyLine_outputEpilog();
}