⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 readwrite.c

📁 该程序主要用于三角网
💻 C
字号:
/* Copyright (c) Colorado School of Mines, 2001.*/
/* All rights reserved.                       */


/*********************** self documentation **********************/
/*****************************************************************************
READWRITE - READ or WRITE a triangulated model

readModel		Read a model in the form produced by writeModel
writeModel		Write a model to a file

******************************************************************************
Function Prototypes:
Model *readModel (FILE *fp);
void writeModel (Model *m, FILE *fp);

******************************************************************************
readModel:
Input:
fp		file pointer to file containing model

writeModel:
Input:
m		pointer to Model
fp		file pointer

******************************************************************************
Author:  Jack K. Cohen, Center for Wave Phenomena, 09/21/90
Modified:  Dave Hale, Center for Wave Phenomena, 11/30/90
	Converted representation of model from ascii to binary for speed.
	Added code to read attributes.
Modified (writeModel):  Craig Artley, Center for Wave Phenomena, 04/08/94
	Corrected bug;  previously the edgeuses and vertextuses of the
	exterior face were not written.
******************************************************************************/

/**************** end self doc ********************************/

#include "Triangles/triP.h"

/* functions defined and used internally */
static void createModel (Model **mptr, Address **fheadptr, FILE *fp);
static void createFace (Model *m, Address **fheadptr, Address **euheadptr,
	size_t sfa, FILE *fp);
static void createEdgeUse (Address **fheadptr, Address **euheadptr,
	Address **vuheadptr, Address **eheadptr, size_t seua, FILE *fp);
static void createVertexUse (Address **euheadptr, Address **vuheadptr,
	Address **vheadptr, size_t svua, FILE *fp);
static void createEdge (Address **euheadptr, Address **eheadptr, size_t sea,
	FILE *fp);
static void createVertex (Address **vuheadptr, Address **vheadptr, size_t sva,
	FILE *fp);
static Address *fillAddress (Address *head, address_t oa, address_t na);
static Address *getAddress (Address *head, address_t oa, address_t *value);

/* macros */
#define DONODE(node, headptr, oa, type)				\
{								\
	int found;						\
	address_t value;					\
	headptr = updateAddressTree(headptr, oa, &found);	\
	if (!found) {						\
		node = (type *) malloc(sizeof(type));		\
		headptr = fillAddress(headptr, oa, node);	\
	} else {						\
		headptr = getAddress(headptr, oa, &value);	\
		node = (type *) value;				\
	}							\
}
#define DOFIELD(node, field, headptr, oa, type)			\
{								\
	int found;						\
	address_t value;					\
	type *field;						\
	headptr = updateAddressTree(headptr, oa, &found);	\
	if (!found) {						\
		field = (type *) malloc(sizeof(type));		\
		headptr = fillAddress(headptr, oa, field);	\
		node->field = field;				\
	} else {						\
		headptr = getAddress(headptr, oa, &value);	\
		node->field = (type *) value;			\
	}							\
}

Model *readModel (FILE *fp)
/*****************************************************************************
readModel - Read a model in the form produced by writeModel
******************************************************************************
Input:
fp		file pointer to file containing model

******************************************************************************
Author:  Jack K. Cohen, Center for Wave Phenomena, 09/21/90
Modified:  Dave Hale, Center for Wave Phenomena, 11/30/90
	Converted representation of model from ascii to binary for speed.
	Added code to read attributes.
******************************************************************************/
{
	Model *m;		/* pointer to model to be returned */
	Address *fhead  = NULL;	/* pointers to binary trees	*/
	Address *euhead = NULL;
	Address *vuhead = NULL;
	Address *ehead  = NULL;
	Address *vhead  = NULL;
	int type;
	
	while(fread(&type,sizeof(int),1,fp)) {
		if (type==MODELTYPE) {
			createModel(&m,&fhead,fp);
		} else if (type==FACETYPE) {
			createFace(m,&fhead,&euhead,m->sfa,fp);
		} else if (type==EDGEUSETYPE) {
			createEdgeUse(&fhead,&euhead,&vuhead,&ehead,
				m->seua,fp);
		} else if (type==VERTEXUSETYPE) {
			createVertexUse(&euhead,&vuhead,&vhead,m->svua,fp);
		} else if (type==EDGETYPE) {
			createEdge(&euhead,&ehead,m->sea,fp);
		} else if (type==VERTEXTYPE) {
			createVertex(&vuhead,&vhead,m->sva,fp);
		} else {
			fprintf(stderr,"invalid type in model\n");
			exit(EXIT_FAILURE);
		}
	}
	return m;
}

static void createModel(Model **mptr, Address **fheadptr, FILE *fp)
{
	Model *m;
	Face *f;
	int found;

	*mptr = m = (Model*)malloc(sizeof(Model));
	fread(m,sizeof(address_t),1,fp);
	if (fread(m,sizeof(Model),1,fp)!=1) {
		fprintf(stderr,"error reading Model\n");
		exit(EXIT_FAILURE);
	}
	*fheadptr = updateAddressTree(*fheadptr,m->f,&found);
	if (!found) {
		f = (Face*)malloc(sizeof(Face));
		*fheadptr = fillAddress(*fheadptr,m->f,f);
		m->f = f;
	} else {
		fprintf(stderr,"Model's first face already exists\n");
		exit(EXIT_FAILURE);
	}
	m->vAdd = NULL;
	m->vDel = NULL;
	m->tAdd = NULL;
	m->tDel = NULL;
	if (m->ma!=NULL && m->sma!=0) {
		m->ma = malloc(m->sma);
		if (fread(m->ma,m->sma,1,fp)!=1) {
			fprintf(stderr,"error reading model attributes\n");
			exit(EXIT_FAILURE);
		}
	} else {
		m->ma = NULL;
	}
}

static void createFace (Model *m, Address **fheadptr, Address **euheadptr,
	size_t sfa, FILE *fp)
{
	Face *of,*f;

	fread(&of,sizeof(Face*),1,fp);
	DONODE(f,*fheadptr,of,Face);
	if (fread(f,sizeof(Face),1,fp)!=1) {
		fprintf(stderr,"error reading Face\n");
		exit(EXIT_FAILURE);
	}
	f->m = m;
	DOFIELD(f,fPrev,*fheadptr,f->fPrev,Face);
	DOFIELD(f,fNext,*fheadptr,f->fNext,Face);
	DOFIELD(f,eu,*euheadptr,f->eu,EdgeUse);
	if (f->fa!=NULL && sfa!=0) {
		f->fa = malloc(sfa);
		if (fread(f->fa,sfa,1,fp)!=1) {
			fprintf(stderr,"error reading FaceAttributes\n");
			exit(EXIT_FAILURE);
		}
	} else {
		f->fa = NULL;
	}
}

static void createEdgeUse (Address **fheadptr, Address **euheadptr,
	Address **vuheadptr, Address **eheadptr, size_t seua, FILE *fp)
{
	EdgeUse *oeu,*eu;
	
	fread(&oeu,sizeof(EdgeUse*),1,fp);
	DONODE(eu,*euheadptr,oeu,EdgeUse);
	if (fread(eu,sizeof(EdgeUse),1,fp)!=1) {
		fprintf(stderr,"error reading EdgeUse\n");
		exit(EXIT_FAILURE);
	}
	if (eu->f==NULL) eu->f = NULL;
	else DOFIELD(eu,f,*fheadptr,eu->f,Face);
	DOFIELD(eu,vu,*vuheadptr,eu->vu,VertexUse);
	DOFIELD(eu,euMate,*euheadptr,eu->euMate,EdgeUse);
	DOFIELD(eu,euCW,*euheadptr,eu->euCW,EdgeUse);
	DOFIELD(eu,euCCW,*euheadptr,eu->euCCW,EdgeUse);
	DOFIELD(eu,e,*eheadptr,eu->e,Edge);
	if (eu->eua!=NULL && seua!=0) {
		eu->eua = malloc(seua);
		if (fread(eu->eua,seua,1,fp)!=1) {
			fprintf(stderr,"error reading edge-use attributes\n");
			exit(EXIT_FAILURE);
		}
	} else {
		eu->eua = NULL;
	}
}

static void createVertexUse (Address **euheadptr, Address **vuheadptr,
	Address **vheadptr, size_t svua, FILE *fp)
{
	VertexUse *ovu,*vu;
	
	fread(&ovu,sizeof(VertexUse*),1,fp);
	DONODE(vu,*vuheadptr,ovu,VertexUse);
	if (fread(vu,sizeof(VertexUse),1,fp)!=1) {
		fprintf(stderr,"error reading VertexUse\n");
		exit(EXIT_FAILURE);
	}
	DOFIELD(vu,eu,*euheadptr,vu->eu,EdgeUse);
	DOFIELD(vu,vuPrev,*vuheadptr,vu->vuPrev,VertexUse);
	DOFIELD(vu,vuNext,*vuheadptr,vu->vuNext,VertexUse);
	DOFIELD(vu,v,*vheadptr,vu->v,Vertex);
	if (vu->vua!=NULL && svua!=0) {
		vu->vua = malloc(svua);
		if (fread(vu->vua,svua,1,fp)!=1) {
			fprintf(stderr,
				"error reading vertex-use attributes\n");
			exit(EXIT_FAILURE);
		}
	} else {
		vu->vua = NULL;
	}
}

static void createEdge (Address **euheadptr, Address **eheadptr, size_t sea,
	FILE *fp)
{
	Edge *oe,*e;
	
	fread(&oe,sizeof(Edge*),1,fp);
	DONODE(e,*eheadptr,oe,Edge);
	if (fread(e,sizeof(Edge),1,fp)!=1) {
		fprintf(stderr,"error reading Edge\n");
		exit(EXIT_FAILURE);
	}
	DOFIELD(e,eu,*euheadptr,e->eu,EdgeUse);
	if (e->ea!=NULL && sea!=0) {
		e->ea = malloc(sea);
		if (fread(e->ea,sea,1,fp)!=1) {
			fprintf(stderr,"error reading edge attributes\n");
			exit(EXIT_FAILURE);
		}
	} else {
		e->ea = NULL;
	}
}

static void createVertex (Address **vuheadptr, Address **vheadptr, size_t sva,
	FILE *fp)
{
	Vertex *ov,*v;
	
	fread(&ov,sizeof(Vertex*),1,fp);
	DONODE(v,*vheadptr,ov,Vertex);
	if (fread(v,sizeof(Vertex),1,fp)!=1) {
		fprintf(stderr,"error reading Vertex");
		exit(EXIT_FAILURE);
	}
	DOFIELD(v,vu,*vuheadptr,v->vu,VertexUse);
	if (v->va!=NULL && sva!=0) {
		v->va = malloc(sva);
		if (fread(v->va,sva,1,fp)!=1) {
			fprintf(stderr,"error reading vertex attributes\n");
			exit(EXIT_FAILURE);
		}
	} else {
		v->va = NULL;
	}
}

static Address *fillAddress(Address *p, address_t oa, address_t na)
/* tree searcher to register the newly allocated address */
{
	int sign;

	if (p == NULL) {  /* not in tree--error */
		fprintf(stderr, "fillAddress called on non-existent node\n");
		exit(EXIT_FAILURE);
	}
	else if ((sign = (int)oa - (int)(p->oaddress)) < 0)
		p->aLeft = fillAddress(p->aLeft, oa, na);
	else if (sign > 0)
		p->aRight = fillAddress(p->aRight, oa, na);
	else /* sign == 0; we've found the entry to fill */
		p->naddress = na;

	return p;
}

static Address *getAddress(Address *p, address_t oa, address_t *value)
/* tree searcher to fetch a newly allocated address */
{
	int sign;

	if (p == NULL) {  /* not in tree--error */
		fprintf(stderr, "getAddress called on non-existent node\n");
		exit(EXIT_FAILURE);
	}
	else if ((sign = (int)oa - (int)(p->oaddress)) < 0)
		p->aLeft = getAddress(p->aLeft, oa, value);
	else if (sign > 0)
		p->aRight = getAddress(p->aRight, oa, value);
	else /* sign == 0; we've found the value to return */
		*value = p->naddress;

	return p;
}


#ifdef TEST
main()
{
	Model *m;

	m = readModel(0,0,0,0,0,0,stdin);
	writeModel(m,0,0,0,0,0,0,stdout);
}
#endif


/* functions defined and used internally */
static void _writeModel (FILE *fp, Model *m, size_t sma);
static void writeFace (FILE *fp, Face *f, size_t sfa);
static void writeEdgeUse (FILE *fp, EdgeUse *eu, size_t seua);
static void writeEdge (FILE *fp, Edge *e, size_t sea);
static void writeVertexUse (FILE *fp, VertexUse *vu, size_t svua);
static void writeVertex (FILE *fp, Vertex *v, size_t sva);

void writeModel (Model *m, FILE *fp)
/*****************************************************************************
writeModel - Write a model to a file
******************************************************************************
Input:
m		pointer to Model
fp		file pointer

******************************************************************************
Author:    Jack K. Cohen, Center for Wave Phenomena, 09/15/90
Modified:  Dave Hale, Center for Wave Phenomena, 11/29/90
	Converted representation of model from ascii to binary for speed.
	Added code to write attributes.
Modified:  Craig Artley, Center for Wave Phenomena, 04/08/94
	Corrected bug;  previously the edgeuses and vertextuses of the
	exterior face were not written.
******************************************************************************/
{
	Face *f;
	EdgeUse *eu,*euFirst;
	Address *vhead=NULL,*ehead=NULL;
	int repeat;


	/* write the model data */
	_writeModel(fp,m,m->sma);

	/* loop over all faces in model */
	f = m->f;
	do {	

		writeFace(fp,f,m->sfa);

		/* loop over all edgeuses in face */
		eu = f->eu;
		do {
		
			/* write edgeuse, edge, vertexuse, and vertex */
			writeEdgeUse(fp,eu,m->seua);
			ehead = updateAddressTree(ehead,eu->e,&repeat);
			if (!repeat) writeEdge(fp,eu->e,m->sea);
			writeVertexUse(fp,eu->vu,m->svua);
			vhead = updateAddressTree(vhead,eu->vu->v,&repeat);
			if (!repeat) writeVertex(fp,eu->vu->v,m->sva);
				
			/* next edgeuse */
			eu = eu->euCW;

		} while (eu!=f->eu);
		
		/* next face */
		f = f->fNext;

	} while (f!=m->f);

	/* loop over all faces in model, looking for the exterior */
	f = m->f;
	do {

		/* find an edgeuse belonging to the exterior face */
		if (f->eu->euMate->f==NULL) {
			eu = f->eu->euMate;
			break;
		} else if (f->eu->euCW->euMate->f==NULL) {
			eu = f->eu->euCW->euMate;
			break;
		} else if (f->eu->euCCW->euMate->f==NULL) {
			eu = f->eu->euCCW->euMate;
			break;
		}

		/* next face */
		f = f->fNext;

	} while (f!=m->f);

	/* confirm the resulting edgeuse belongs to the exterior */
	if (eu->f!=NULL) {
		fprintf(stderr,"writeModel: can't find exterior face\n");
		exit(EXIT_FAILURE);
	}

	/* loop over all edgeuses in exterior face */
	euFirst = eu;
	do {
		/* write edgeuse and vertexuse (edges & vertices done above) */
		writeEdgeUse(fp,eu,m->seua);
		writeVertexUse(fp,eu->vu,m->svua);

		/* next edgeuse */
		eu = eu->euCW;

	} while (eu!=euFirst);
}

static void _writeModel(FILE *fp, Model *m, size_t sma)
{
	int type=MODELTYPE;
	fwrite(&type,sizeof(int),1,fp);
	fwrite(&m,sizeof(Model*),1,fp);
	fwrite(m,sizeof(Model),1,fp);
	if (m->ma!=NULL && sma!=0) fwrite(m->ma,sma,1,fp);
}

static void writeFace(FILE *fp, Face *f, size_t sfa)
{
	int type=FACETYPE;
	fwrite(&type,sizeof(int),1,fp);
	fwrite(&f,sizeof(Face*),1,fp);
 	fwrite(f,sizeof(Face),1,fp);
	if (f->fa!=NULL && sfa!=0) fwrite(f->fa,sfa,1,fp);
}

static void writeEdgeUse(FILE *fp, EdgeUse *eu, size_t seua)
{
	int type=EDGEUSETYPE;
	fwrite(&type,sizeof(int),1,fp);
	fwrite(&eu,sizeof(EdgeUse*),1,fp);
	fwrite(eu,sizeof(EdgeUse),1,fp);
	if (eu->eua!=NULL && seua!=0) fwrite(eu->eua,seua,1,fp);
}

static void writeEdge(FILE *fp, Edge *e, size_t sea)
{
	int type=EDGETYPE;
	fwrite(&type,sizeof(int),1,fp);
	fwrite(&e,sizeof(Edge*),1,fp);
	fwrite(e,sizeof(Edge),1,fp);
	if (e->ea!=NULL && sea!=0) fwrite(e->ea,sea,1,fp);
}

static void writeVertexUse(FILE *fp, VertexUse *vu, size_t svua)
{
	int type=VERTEXUSETYPE;
	fwrite(&type,sizeof(int),1,fp);
	fwrite(&vu,sizeof(VertexUse*),1,fp);
	fwrite(vu,sizeof(VertexUse),1,fp);
	if (vu->vua!=NULL && svua!=0) fwrite(vu->vua,svua,1,fp);
}

static void writeVertex(FILE *fp, Vertex *v, size_t sva)
{
	int type=VERTEXTYPE;
	fwrite(&type,sizeof(int),1,fp);
	fwrite(&v,sizeof(Vertex*),1,fp);
	fwrite(v,sizeof(Vertex),1,fp);
	if (v->va!=NULL && sva!=0) fwrite(v->va,sva,1,fp);
}


#ifdef TEST
main()
{
	Model *m;

	m = makeModel(1.0,2.0,5.0,6.0);
	writeModel(m,stdout);
}
#endif


Address *updateAddressTree(Address *p, address_t oa, int *found)
/* add nodes to a tree on the fly--after Kernighan and Ritchie, */
/* The C Programming Language, 2nd Edition, p. 139ff. */
/* Used internally in readModel() and writeModel(). */
{
	int sign;

	if (p == NULL) {  /* not in tree */
		p = (Address*) malloc(sizeof(Address));
		p->oaddress = oa;
		p->aLeft = p->aRight = NULL;
		*found = 0;
	}
	else if ((sign = ((int)oa - (int)(p->oaddress))) < 0)
		p->aLeft = updateAddressTree(p->aLeft, oa, found);
	else if (sign > 0)
		p->aRight = updateAddressTree(p->aRight, oa, found);
	else /* sign == 0; we've found the entry */
		*found = 1;

	return p;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -