File: [local] / OpenXM_contrib2 / asir2000 / plot / smoothing.c (download)
Revision 1.3, Tue Oct 24 01:53:53 2000 UTC (23 years, 11 months ago) by takayama
Branch: MAIN
CVS Tags: maekawa-ipv6 Changes since 1.2: +29 -2
lines
"method" menu is added to the print button.
|
/* $OpenXM: OpenXM_contrib2/asir2000/plot/smoothing.c,v 1.3 2000/10/24 01:53:53 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_output_bezier_PS(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_output_bezier_PS(struct polyLine *pl) {
int n,i,m;
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 ");
i=0;
m = n-1-((n-1)/3)*3;
fprintf(Fp," %d %d ",translateX(pl->x[i]),translateY(pl->y[i]));
fprintf(Fp," moveto \n ");
for (i=1; i<= ((n-1)/3)*3; i++) {
fprintf(Fp," %d %d ",translateX(pl->x[i]),translateY(pl->y[i]));
if ( i%3 == 0) fprintf(Fp," curveto ");
}
for (i=n-m; i<n; i++) {
fprintf(Fp," %d %d lineto ",translateX(pl->x[i]),translateY(pl->y[i]));
}
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,"0.1 setlinewidth \n");
fprintf(Fp,"2 setlinecap \n");
fprintf(Fp,"2 setlinejoin \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]]); */
polyLine_output_bezier_PS(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();
}