三维CAD塑造——基于所述基本数据结构一半欧拉操作模型

三维CAD塑造——基于所述基本数据结构一半欧拉操作模型(elar, B_REP)

(欧拉操作  三维CAD建模课程 三维CAD塑造 高曙明老师  渲染框架 brep 带洞 带柄 B_REP brep elar 扫成 扫成操作)

今年选了高老师的三维CAD建模课。zju选了这课应该就知道最后要做一个程序作业——基于半边数据结构的基本欧拉操作实现建模。要求必须建带有洞的模型。

(欧拉操作  三维CAD建模课 三维CAD建模 高署明老师  渲染框架 brep 带洞 带柄 B_REP brep elar 扫成 扫成操作)

3.3 欧拉操作的选择(6维空间的5维超平面)

v    e     f     h   r    s     Operator

1    1     0    0   0    0       mev

0    1     1    0   0    0       mef

1    0     1    0   0    1       mvfs

0   -1     0    0   1    0       kemr

0    0    -1   1    1    0      kfmrh

mvsf:生成含有一个点的面,包含一个空环,而且构成一个新的体

mev:生成一个新的点e2,连接该点到已有点v1。构造一条新的边

mef:连接面f1上的两个点v1,v2,生成一条新边e,并产生一个新面

kemr:删除一条边e。生成该边某一邻面上的新的内环

kfmrh:删除与面f1相接触的一个面f2,生成面f1上的一个内环,并形成体上的一个通孔

主要就是实现这五个欧拉操作就能够了。

以下主要是记录下我在作业中半边数据结构以及基本欧拉操作的实现。

#ifndef __HALF_EDGE_STRUCTURE__
#define __HALF_EDGE_STRUCTURE__

#include <stdlib.h>

struct Solid;
struct Face;
struct Loop;
struct HalfEdge;
struct Vertex;
struct Edge;

struct Solid
{
	int id;
	Face *faces; // list of all faces to construct this solid
	Edge *edges; // list of all edges to construct this solid->to build the frame
	Solid *next;
	Solid *pre;

	int vnum;//the count of all vertexs
	int fnum;//the count of all faces
	int lnum;//the count of all loops

	Solid() : id(0), faces(NULL), edges(NULL), next(NULL), pre(NULL), fnum(0), vnum(0), lnum(0){}
};

struct Face
{
	int id;
	Solid *solid; // the solid which the face belong to
	Loop *out_lp; // out loop of the face--construct the face
	Loop *inner_lp;//inner_lp of the face--inner loop
	Face *next;
	Face *pre;
	int innum;//the count of inner loops

	Face() : id(0), solid(NULL), out_lp(NULL), next(NULL), pre(NULL), inner_lp(NULL), innum(0){}
};

struct Loop
{
	int id;
	HalfEdge *halfedges; // list of all halfeges to construct this loop
	Face *face; // the face that constructed by this loop
	Loop *next;
	Loop *pre;

	Loop() : id(0), halfedges(NULL), face(NULL), next(NULL), pre(NULL){}
};

struct Edge
{
	HalfEdge *half_l; //the edge's left halfedge
	HalfEdge *half_r; //the edge's right halfedge
	Edge *next;
	Edge *pre;

	Edge() : half_l(NULL), half_r(NULL), next(NULL), pre(NULL){}
};

struct HalfEdge
{
	Edge *edge; //this halfedge belong to which edge
	Vertex *sv; //the start vertex of this halfedge
	Vertex *ev; //the end vertex of this halfedge
	Loop *lp; //pointer to the loop that this halfedge belong to
	HalfEdge *next;
	HalfEdge *pre;
	HalfEdge *brother;

	HalfEdge() : edge(NULL), sv(NULL), lp(NULL), next(NULL), pre(NULL), brother(NULL){}
};

struct Vertex
{
	int id;
	double coordinate[3];//coordinate of the vertex (x, y, z)
	Vertex *next;
	Vertex *pre;

	Vertex(double x, double y, double z) : id(0), next(NULL), pre(NULL)
	{
		coordinate[0] = x;
		coordinate[1] = y;
		coordinate[2] = z;
	}
};

#endif

以下是五种欧拉操作的实现代码

elar_operator.h

#ifndef __ELAR_OPERATOR__
#define __ELAR_OPERATOR__

#include "half_edge_structure.h"
#include <vector>

using namespace std;

class ElarOperator
{
public:
	ElarOperator()
	{
		v_list.clear();
		sweep_list.clear();
		l_list.clear();
	}

	std::vector<Vertex *> getV_list()
	{
		return v_list;
	}

	std::vector<Face *> getSweep_list()
	{
		return sweep_list;
	}

	std::vector<Loop *> getLoop_list()
	{
		return l_list;
	}

	void addEdgeIntoSolid(Edge *edge, Solid *&solid);
	void addFaceIntoSolid(Face *face, Solid *&solid);
	void addLoopIntoFace(Loop *loop, Face *face);
	Solid *mvfs(double point[3], Vertex *&vertex);
	HalfEdge *mev(Vertex *sv, double point[3], Loop *lp);
	Loop *mef(Vertex *sv, Vertex *ev, Loop *lp, bool mark);
	Loop *kemr(Vertex *sv, Vertex *ev, Loop *lp);
	void kfmrh(Face *fa, Face *fb);
	void sweep(double dir[3], double dist);

private:
	std::vector<Vertex *> v_list;
	std::vector<Loop *> l_list;
	std::vector<Face *> sweep_list;
};

#endif

elar_operator.cpp

#include "elar_operator.h"
#include <cstdio>

Solid *ElarOperator::mvfs(double point[3], Vertex *&vertex)
{
	Solid *solid = new Solid();
	Face *face = new Face();
	Loop *out_lp = new Loop();
	vertex = new Vertex(point[0], point[1], point[2]);

	vertex->id = solid->vnum;
	out_lp->id = solid->lnum;
	face->id = solid->fnum;

	l_list.push_back(out_lp);
	//printf("%lf %lf %lf\n", vertex->coordinate[0], vertex->coordinate[1], vertex->coordinate[2]);
	v_list.push_back(vertex);//store the vertex by order
	solid->vnum += 1;//increase the num of vertexs
	solid->fnum += 1;//increase the num of faces
	solid->lnum += 1;//increase the num of loops

	solid->faces = face;
	face->solid = solid;

	face->out_lp = out_lp;
	out_lp->face = face;

	return solid;
}

HalfEdge *ElarOperator::mev(Vertex *sv, double point[3], Loop *loop)
{
	Solid *solid = loop->face->solid;
	Edge *edge = new Edge();//create a new edge
	HalfEdge *half_l = new HalfEdge();
	HalfEdge *half_r = new HalfEdge();
	Vertex *ev = new Vertex(point[0], point[1], point[2]);

	ev->id = solid->vnum;
	v_list.push_back(ev);//store the vertex by order
	solid->vnum += 1;//remember to increase the vertex num of the solid

	half_l->sv = sv;
	half_l->ev = ev;
	half_r->sv = ev;
	half_r->ev = sv;

	edge->half_l = half_l;
	edge->half_r = half_r;
	half_l->edge = edge;
	half_r->edge = edge;

	half_r->brother = half_l;
	half_l->brother = half_r;

	half_l->lp = loop;
	half_r->lp = loop;

	//add the new two halfedges into the loop
	if (loop->halfedges == NULL)
	{
		half_l->next = half_r;
		half_r->next = half_l;

		half_l->pre = half_r;
		half_r->pre = half_l;
		loop->halfedges = half_l;
	}
	else
	{
		HalfEdge *thalf = loop->halfedges;
		while (thalf->ev != sv)thalf = thalf->next;
		half_r->next = thalf->next;
		thalf->next->pre = half_r;
		thalf->next = half_l;
		half_l->pre = thalf;
		half_l->next = half_r;
		half_r->pre = half_l;
	}

	//add the edge into the edge list of solid
	addEdgeIntoSolid(edge, solid);
	return half_l;
}

Loop *ElarOperator::mef(Vertex *sv, Vertex *ev, Loop *loop, bool mark)
{
	Solid *solid = loop->face->solid;
	Edge *edge = new Edge();
	HalfEdge *half_l = new HalfEdge();
	HalfEdge *half_r = new HalfEdge();
	Loop *newLoop = new Loop();

	half_l->sv = sv;
	half_l->ev = ev;
	half_r->sv = ev;
	half_r->ev = sv;

	half_r->brother = half_l;
	half_l->brother = half_r;

	half_l->edge = edge;
	half_r->edge = edge;
	edge->half_l = half_l;
	edge->half_r = half_r;

	//add the new two halfedge into the loop
	HalfEdge *thalf = loop->halfedges;
	HalfEdge *tmpa, *tmpb, *tmpc;
	while (thalf->ev != sv)thalf = thalf->next;
	tmpa = thalf;

	while (thalf->ev != ev)thalf = thalf->next;
	tmpb = thalf;

	thalf = thalf->next;
	while (thalf->ev != ev)thalf = thalf->next;
	tmpc = thalf;

	//divide the big loop into two small loop
	half_r->next = tmpa->next;
	tmpa->next->pre = half_r;
	tmpa->next = half_l;
	half_l->pre = tmpa;

	half_l->next = tmpb->next;
	tmpb->next->pre = half_l;
	tmpb->next = half_r;
	half_r->pre = tmpb;
	loop->halfedges = half_l;
	newLoop->halfedges = half_r;
	half_l->lp = loop;
	half_r->lp = newLoop;

	Face *face = new Face();

	newLoop->id = solid->lnum;
	solid->lnum += 1;
	l_list.push_back(newLoop);
	//add face into the face list of solid
	addFaceIntoSolid(face, solid);

	addLoopIntoFace(newLoop, face);

	if (tmpc == tmpb)
	{
		if (mark)//only the face in the bottom
		{
			sweep_list.push_back(half_l->lp->face);
		}
	}
	else
	{
		sweep_list.push_back(half_r->lp->face);
	}

	//add edge into the edge list of solid
	addEdgeIntoSolid(edge, solid);

	return loop;
}

Loop *ElarOperator::kemr(Vertex *sv, Vertex *ev, Loop *loop)//sv must belong to the outer loop
{
	HalfEdge *tmpa, *tmpb, *hal;
	Face *face = loop->face;
	Loop *inlp = new Loop();
	Solid *solid = loop->face->solid;

	hal = loop->halfedges;

	while (hal->sv != sv || hal->ev != ev)hal = hal->next;
	tmpa = hal;

	while (hal->sv != ev || hal->ev != sv)hal = hal->next;
	tmpb = hal;

	tmpb->pre->next = tmpa->next;
	tmpa->pre->next = tmpb->next;

	loop->face->solid->faces->out_lp->halfedges = tmpa->pre;

	inlp->halfedges = tmpb->pre;
	tmpb->pre->lp = inlp; 

	inlp->id = solid->lnum;
	solid->lnum += 1;
	l_list.push_back(inlp);

	addLoopIntoFace(inlp, tmpa->pre->brother->lp->face);

	delete tmpa;
	delete tmpb;

	return NULL;
}

void ElarOperator::kfmrh(Face *fa, Face *fb)//fa indicate the outface, fb indicate the innerface
{
	Loop *loop = fb->out_lp;
	addLoopIntoFace(loop, fa);
	fa->solid->lnum -= 1;
	fa->solid->fnum -= 1;

	Solid *solid = fa->solid;
	Face *face = solid->faces;
	if (face == fb)
	{
		solid->faces = face->next;
	}
	else
	{
		Face *tf = face;
		while (face != fb && face != NULL)
		{
			tf = face;
			face = face->next;
		}
		tf->next = face->next;
	}
	delete fb;
}

void ElarOperator::sweep(double dir[3], double d)
{
	Vertex *startv, *nextv, *upv, *upprev;
	HalfEdge *he, *suphe, *uphe;
	double point[3];

	vector<Face *>::iterator ite;
	for (ite = sweep_list.begin(); ite != sweep_list.end(); ++ite)
	{

		//solve the first vertex when process the sweeping operator
		Loop *loop = (*ite)->out_lp;
		he = loop->halfedges;
		startv = he->sv;
		point[0] = startv->coordinate[0] + d*dir[0];
		point[1] = startv->coordinate[1] + d*dir[1];
		point[2] = startv->coordinate[2] + d*dir[2];

		suphe = mev(startv, point, loop);//acquire the first down_to_up halfedge
		upprev = suphe->ev;//record the fist up vertex as the pre vertex
		he = he->next;
		nextv = he->sv;

		Loop *lp = loop;

		while (nextv != startv)
		{
			point[0] = nextv->coordinate[0] + d*dir[0];
			point[1] = nextv->coordinate[1] + d*dir[1];
			point[2] = nextv->coordinate[2] + d*dir[2];
			uphe = mev(nextv, point, lp);
			upv = uphe->ev;

			lp = mef(upprev, upv, loop, false);

			upprev = upv;
			he = he->next;
			nextv = he->sv;
		}
		mef(upprev, suphe->ev, loop, false);

	}
}

inline
void ElarOperator::addEdgeIntoSolid(Edge *edge, Solid *&solid)
{
	Edge *te = solid->edges;

	if (te == NULL)solid->edges = edge;
	else{
		while (te->next != NULL)te = te->next;
		te->next = edge;
		edge->pre = te;
	}
}

inline
void ElarOperator::addFaceIntoSolid(Face *face, Solid *&solid)
{
	Face *tface = solid->faces;
	if (tface == NULL)
	{
		solid->faces = face;
	}
	else
	{
		while (tface->next != NULL)tface = tface->next;
		tface->next = face;
		face->pre = tface;
	}
	face->solid = solid;

	face->id = solid->fnum;

	solid->fnum += 1;// increase the num of faces
}

inline
void ElarOperator::addLoopIntoFace(Loop *loop, Face *face)
{
	loop->face = face;

	//there is only one out loop but there may have lots of inner loop
	if (face->out_lp == NULL)
	{
		face->out_lp = loop;
	}
	else
	{
		Loop *tlp = face->inner_lp;
		if (tlp == NULL)face->inner_lp = loop;
		else
		{
			while (tlp->next != NULL)tlp = tlp->next;
			tlp->next = loop;
			loop->pre = tlp;
		}
		face->innum += 1;
	}
}

上面就是基本实现,然后加上自己的输入输出就能够实现带洞模型的建造。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvSUFjY2VwdGVk/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" >

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvSUFjY2VwdGVk/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" >

以上就是简单建了带洞模型,当然能够在体内建很多其它的洞,建不同形状的洞,这样就完毕了作业要求。

各个操作都挺简单,关键是mef的时候要注意选取面环时的法向问题就能够了。用右手规则比划一下就能非常easy的确定了。每一个洞扫成完毕后要记得kfmrh来得到这个洞。

ok,就这些了。

以上代码链接:http://download.csdn.net/detail/iaccepted/8167679

版权声明:本文博主原创文章。博客,未经同意不得转载。

时间: 2024-10-08 15:41:05

三维CAD塑造——基于所述基本数据结构一半欧拉操作模型的相关文章

三维CAD建模——基于半边数据结构的基本欧拉操作建模

三维CAD建模--基于半边数据结构的基本欧拉操作建模(elar, B_REP) 今年选了高老师的三维CAD建模课,zju选了这课应该就知道最后要做一个程序作业--基于半边数据结构的基本欧拉操作实现建模.要求必须建带有洞的模型. 3.3 欧拉操作的选择(6维空间的5维超平面) v    e     f     h   r    s     Operator 1    1     0    0   0    0       mev 0    1     1    0   0    0       m

数据结构18——欧拉函数

1.欧拉函数是指:对于一个正整数n,小于n且和n互质的正整数(包括1)的个数,记作φ(n) . 2.通式:φ(x)=x*(1-1/p1)*(1-1/p2)*(1-1/p3)*(1-1/p4)-..(1-1/pn),其中p1, p2--pn为x的所有质因数,x是不为0的整数. φ(1)=1(唯一和1互质的数就是1本身). 3.对于质数p,φ(p) = p - 1. 4.欧拉定理:对于互质的正整数a和n,有aφ(n) ≡ 1 mod n. 5.欧拉函数是积性函数--若m,n互质,φ(mn)=φ(m)

数据结构之链表单向操作总结

链表是数据结构的基础内容之一,下面就链表操作中的创建链表.打印链表.求取链表长度.判断链表是否为空.查找结点.插入结点.删除结点.逆转链表.连接链表.链表结点排序等进行总结. 1.创建表示结点的类,因为链表操作中需要比较结点,因此结点需要实现comparable接口. public class Node implements Comparable<Node> { private Object data; private Node next; //构造函数 public Node() { thi

poj 2478 Farey Sequence(基于素数筛法求欧拉函数)

http://poj.org/problem?id=2478 求欧拉函数的模板. 初涉欧拉函数,先学一学它基本的性质. 1.欧拉函数是求小于n且和n互质(包括1)的正整数的个数.记为φ(n). 2.欧拉定理:若a与n互质,那么有a^φ(n) ≡ 1(mod n),经常用于求幂的模. 3.若p是一个质数,那么φ(p) = p-1,注意φ(1) = 1. 4.欧拉函数是积性函数: 若m与n互质,那么φ(nm) = φ(n) * φ(m). 若n = p^k且p为质数,那么φ(n) = p^k - p

基于spark1.4.1的sparkR的实例操作

[Author]: kwu 基于spark1.4.1的sparkR的实例操作,sparkR的操作基本语法与R一致,其中添加了rJava.rhdfs.SparkR的依赖库的支持. 1.集群启动SparkR 输入 bdcmagicR 关于启动脚本的封装参看 : http://blog.csdn.net/bdchome/article/details/48092499 2.加载依赖库 library("rJava") library("rhdfs") library(&q

如何在CAD编辑器中将CAD图纸转换成PDF文件,具体要怎么操作?

如何在CAD编辑器中将CAD图纸转换成PDF文件,具体要怎么操作?在平常的工作中,建筑设计师们借助CAD编辑器没编辑一张CAD图纸都需要进行查看,但是CAD图纸均为dwg格式的,这样不方便我们进行查看,很多时候就需要将CAD图纸转换成PDF文件,这样就方便我们查看了,但是如何在CAD编辑器中将CAD图纸转换成PDF文件,具体要怎么操作?有什么好的办法吗?下面小编就利用迅捷CAD编辑器标准版来教教大家具体操作方法,希望能够帮助到你们. 第一步:打开电脑,在电脑中打开一个能够进行搜索的浏览器,在浏览

将CAD图纸转换成GIF动态图纸应如何进行操作?

将CAD图纸转换成GIF动态图纸应如何进行操作?我们会经常在工作中遇到的情况就是需要将CAD图纸转换成您想要的格式,例如将CAD转换成图片的格式,但是图片也是有很多种格式的,但是我们是需要将CAD图纸转换成图片中的GIF动态图纸格式我们应该如何进行操作呢,今天小编就要来教教大家将CAD图纸转换成GIF动态图纸应如何进行操作的全部步骤,希望能够帮助到大家! 步骤一:需要进行图纸格式转换的,必须要有一款好用的转换器软件,您首先要打开你们电脑上面的迅捷CAD转换器软件,电脑上面没有这款软件的可以去到软

基于数组的自定义数据结构1-图路径与编号二维数组

在有限的二维数组范围内按行按列对每一个元素位置进行编号,此时对于编号cnt我们可以以此为bridge建立关系,方便查找: 示例代码如下: 1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 using namespace std; 5 const int maxn = 100; 6 const int dx[]={0,0,1,-1}; 7 const int dy[]={1,-1,0,0}; 8 9

数据结构——树的简单操作集合

非常多数据结构的书上解说数据机构时都是採用伪代码实现.事实上感觉蛮不直观的.所以对于全部的数据结构操作我都将其用C实现一遍. 树是学习二叉树的基础,也是后面理解B树.B+树的等树的基础,以下就给出树的几个简单操作,方便理解. 数据结构 //-------数据结构---------------------------------------- #define m 3 //定义度为3的树 typedef char datatype; typedef struct node { datatype da