/*
四种数据结构都采用链表存储结构,文件输入输出都使用格式化输入
输出fscanf、fprintf.四个表都设置全局头结点
fun函数:
对于三角形表,三个顶点两两组合成三条边,用每次组合出的边生成
边表与边序号三角形表:每组合出一条边便到扔到cheak函数里去建立
边,每进去一条边要返回一个边编号,返回的边编号恰好能用来为边
序号三角形表赋值
cheak函数里去建立边过程:
三角形一个边的两个点进来后查找边表里是否有对应边,若有,
则为边表第二个三角形编号赋值,并返回这个边编号给三角形2
若没有,则新生成一个边结点,为边结点第一个三角形编号,
并返回这个边编号给三角形2
找边界线
先把边界线存到数组array,接着,任选某条边的一个顶点,另一个
顶点必然是下一个顶点第一个边,依次循环
测试数据(即边表、三角形表文件格式):
9
0 1 2 3
1 2 3 4
2 3 4 5
3 4 5 6
4 5 6 7
5 6 7 8
6 7 8 9
7 8 9 10
8 9 10 11
10
0 0 1 2
1 0 2 3
2 1 7 2
3 2 4 3
4 2 4 5
5 2 5 7
6 3 4 6
7 4 5 6
8 5 6 8
9 5 7 8
*/
#include <stdlib.h>
#include <stdio.h>
#define maxsize 100
///点
typedef struct point
{
int point_tag;//点编号
double x;
double y;
double z;
struct point *next;
} point;
///三角形
typedef struct Tri
{
int Tri_tag;//三角形编号
int point1_tag;
int point2_tag;
int point3_tag;
struct Tri *next;
} Tri;
///边
typedef struct Arc
{
int e_tag;//边编号
int point1_tag;
int point2_tag;
int Tri_tag1;
int Tri_tag2;
struct Arc *next;
} Arc;
///三角形2
typedef struct Tri_new
{
int Tri_new_tag;//三角形编号
int Tri_new_e1;//第一条边编号
int Tri_new_e2;//第二条边编号
int Tri_new_e3;//第三条边编号
struct Tri_new *next;
} Tri_new;
point *P;//点链表头结点
Tri *T;//三角形链表头结点
Arc *E;//边链表头结点
Tri_new *TT;//边链表头结点
///为四个表表头分配空间,并初始化表头标号-1
void creat_head()
{
P=(point *)malloc(sizeof(point));
P->next=NULL;
P->point_tag=-1;
T=(Tri *)malloc(sizeof(Tri));
T->next=NULL;
T->Tri_tag=-1;
E=(Arc *)malloc(sizeof(Arc));
E->next=NULL;
E->e_tag=-1;
TT=(Tri_new *)malloc(sizeof(Tri_new));
TT->next=NULL;
TT->Tri_new_tag=-1;
}
FILE *fp;
///初始化顶点表
void creat_Point()
{
point *r=P;
int num_point,i;
fp=fopen("data.txt","r");
fscanf(fp,"%d",&num_point);
printf("点:\n");
for(i=0; i<num_point; i++)
{
point *p=(point *)malloc(sizeof(point));
fscanf(fp,"%d %lf %lf %lf",&(p->point_tag),&(p->x),&(p->y),&(p->z));
printf("%d %.2f %.2f %.2f\n",(p->point_tag),(p->x),(p->y),(p->z));
//p->point_tag=i;
r->next=p;
r=p;
}
r->next=NULL;
}
///初始化三角形表
void creat_Tri()
{
Tri *r=T;
int num_Tri,i;
fscanf(fp,"%d",&num_Tri);
printf("\n三角形:\n");
for(i=0; i<num_Tri; i++)
{
Tri *p=(Tri *)malloc(sizeof(Tri));
fscanf(fp,"%d %d %d %d",&(p->Tri_tag),&(p->point1_tag),&(p->point2_tag),&(p->point3_tag));
printf("%d %d %d %d\n",(p->Tri_tag),(p->point1_tag),(p->point2_tag),(p->point3_tag));
//p->Tri_tag=i;
r->next=p;
r=p;
}
r->next=NULL;
}
/*三角形一个边的两个点进来后查找边表里是否有对应边,若有,
则为边表第二个三角形编号赋值,并返回这个边编号给三角形2
若没有,则新生成一个边结点,为边结点第一个三角形编号,
并返回这个边编号给三角形2*/
int cheak(int a,int b,int Tri_tag)
{
Arc *p=E;
Arc *ee=NULL;
while(p->next!=NULL)
{
if((p->next->point1_tag==a&&p->next->point2_tag==b)||(p->next->point1_tag==b&&p->next->point2_tag==a))//说明该边已建立
{
p->next->Tri_tag2=Tri_tag;
//printf("边出:%d\n",p->next->e_tag);
return p->next->e_tag;
break;
}
p=p->next;
}
if(p->next==NULL)////说明该边还没建立
{
ee=(Arc *)malloc(sizeof(Arc));
ee->next=NULL;
ee->point1_tag=a;
ee->point2_tag=b;
ee->e_tag=(p->e_tag)+1;//下一个结点编号为上一个结点编号加1
ee->Tri_tag1=Tri_tag;
ee->Tri_tag2=-1;
p->next=ee;//把生成的新节点连到边表中
//printf("边出:%d\n",ee->e_tag);
return ee->e_tag;
}
return 111;
}
/*对于三角形表,三个顶点两两组合成一条边,用每次组合出的边生成边表与边序号三角形
表:每组合出一条边便到扔到cheak函数里去建立边,每进去一条边当然要返回一个边编号,
返回的边编号恰好能用来为边序号三角形表赋值
*/
void fun()
{
T=T->next;
Tri_new *r=TT;
while(T)
{
Tri_new * tt=(Tri_new *)malloc(sizeof(Tri_new));
tt->Tri_new_tag=(r->Tri_new_tag)+1;
tt->Tri_new_e1=cheak(T->point1_tag,T->point2_tag,T->Tri_tag);
tt->Tri_new_e2=cheak(T->point1_tag,T->point3_tag,T->Tri_tag);
tt->Tri_new_e3=cheak(T->point2_tag,T->point3_tag,T->Tri_tag);
T=T->next;
///尾插
r->next=tt;
r=tt;
}
r->next=NULL;
}
///把边表,边序号三角形写入到文件
void write()
{
FILE *fb=fopen("result.txt","w");
Arc *p=E->next;//边
Tri_new *q=TT->next;//三角形
printf("边:\n");
while(p)
{
///五个数据
fprintf(fb,"%d %d %d %d %d\n",p->e_tag,p->point1_tag,p->point2_tag,p->Tri_tag1,p->Tri_tag2);
printf("%d %d %d %d %d\n",p->e_tag,p->point1_tag,p->point2_tag,p->Tri_tag1,p->Tri_tag2);
p=p->next;
}
fprintf(fb,"\n");
printf("边序号三角形:\n");
while(q)
{
///四个数据
fprintf(fb,"%d %d %d %d\n",q->Tri_new_tag,q->Tri_new_e1,q->Tri_new_e2,q->Tri_new_e3);
printf("%d %d %d %d\n",q->Tri_new_tag,q->Tri_new_e1,q->Tri_new_e2,q->Tri_new_e3);
q=q->next;
}
}
///找边界线函数,先把边界线存到数组array,再从数组中把边界线点找出输出
void find_line()
{
Arc array[maxsize];
int top=-1;
Arc *p=E->next;
while(p)
{
if(p->Tri_tag2==-1)
{
array[++top]=*p;
}
p=p->next;
}
printf("找边界点\n");
int i,tag,n=top;//tag用来存储当前边没被输出的那个点,同时也一定是下一条边界线起点
printf("%d->",array[0].point1_tag);//以第一条边第一个点为起点
tag=array[0].point2_tag;//当前边的第二个点,同时也一定是第二条边界线起点
///把已经找到的边置为-1,是为了下一次搜索跳过它
array[0].point1_tag=-1;
array[0].point2_tag=-1;
while(top!=0)//还有1~top之间边搜索
{
for(i=0; i<=n; i++)
{
if(array[i].point1_tag==tag)
{
printf("%d->",array[i].point1_tag);
tag=array[i].point2_tag;
array[i].point1_tag=-1;
array[i].point2_tag=-1;
break;
}
if(array[i].point2_tag==tag)
{
printf("%d->",array[i].point2_tag);
tag=array[i].point1_tag;
array[i].point1_tag=-1;
array[i].point2_tag=-1;
break;
}
}
top--;
}
}
int main()
{
///初始化四个链表顶点表、三角形表、边表、边序列三角形表的头结点
creat_head();
///从文件读取顶点表
creat_Point();
///从文件读取三角形表
creat_Tri();
///构建边表、边序列三角形表
fun();
///将边表、边序列三角形表输入到文件
write();
printf("已输出至文件result.txt!\n\n");
///找边界线
find_line();
}