三维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" alt="">

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

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

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

ok,就这些了。

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

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

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

  1. 三维CAD——基于B_rep的建模操作

    内容来自高老师的<三维CAD建模>课,本文就主要介绍半边结构和欧拉操作以及代码实现. 1. 边界表示法及其数据结构 · 拓扑结构 a.拓扑元素:面.边.点.体 b.拓扑关系:9种.V{V} ...

  2. 梦想MxWeb3D,三维CAD协同设计平台 2019.04.09更新

    SDK开发包下载地址: http://www.mxdraw.com/ndetail_10140.html 在线演示网址: http://www.mxdraw.com:3000/ 1.  增加上传dwg ...

  3. 转载:点云上实时三维目标检测的欧拉区域方案 ----Complex-YOLO

    感觉是机器翻译,好多地方不通顺,凑合看看 原文名称:Complex-YOLO: An Euler-Region-Proposal for  Real-time 3D Object Detection ...

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

    http://poj.org/problem?id=2478 求欧拉函数的模板. 初涉欧拉函数,先学一学它主要的性质. 1.欧拉函数是求小于n且和n互质(包含1)的正整数的个数. 记为φ(n). 2. ...

  5. 基于SwiperJs的H5/移动端下拉刷新上拉加载更多的效果

    最早时,公司的H5项目中曾用过点击一个"加载更多"的DOM元素来实现分页的功能,后来又用过网上有人写的一个上拉加载更多的插件,那个插件是页面将要滚动到底部时就自动请求数据并插入到页 ...

  6. 基于SwiperJs的H5/移动端下拉刷新上拉加载更多

    最早时,公司的H5项目中曾用过点击一个"加载更多"的DOM元素来实现分页的功能,后来又用过网上有人写的一个上拉加载更多的插件,那个插件是页面将要滚动到底部时就自动请求数据并插入到页 ...

  7. 数据结构&图论:欧拉游览树

    ETT可以称为欧拉游览树,它是一种和欧拉序有关的动态树(LCT是解决动态树问题的一种方案,这是另一种) dfs序和欧拉序是把树问题转化到区间问题上然后再用数据结构去维护的利器 通过借助这两种形式能够完 ...

  8. Python中基于Unpacking与Packing进行分割,组合操作的嵌套元组数据结构的应用

    对于二叉树,图等,Python可采用基于Packing与Unpacking形成的嵌套元组数据结构来模拟,这里Packing指,比如a=b,c则,a就成了一个包含b,c的元组,Unpacking是指,比 ...

  9. 梦想MxWeb3D,三维CAD协同设计平台 2019.05.05更新

    SDK开发包下载地址: http://www.mxdraw.com/ndetail_20140.html 在线演示网址: http://www.mxdraw.com:3000/ 1.  增加CAD绘图 ...

随机推荐

  1. Codeforces 325D

    #include <cstdio> #include <algorithm> #include <cstring> #include <cstdlib> ...

  2. fuel iso光盘刻录机usb Driver 烧录

    ISO image to a DVD or burn the IMG file to a USB drive For a bare-metal installation ipmitool, HP iL ...

  3. 将Controller中的数据传递到View中显示

    如何将Controller 中的数据传送到View 步骤: (1)要有数据,如果要用到对象可以在Model 中定义对应的类 (2)要有装数据的容器: System.Text.StringBuilder ...

  4. ViewDragHelper练习使用

    转载博客地址:http://www.cnblogs.com/flyme2012/p/4076674.html 这个Demo是用来练习VIewDragHelper的,也是仿照网上一个大神的代码.我通过他 ...

  5. 用事件与CSS改变按钮不同状态下的颜色

    目标效果: 表单的群发按钮,在鼠标悬停时为深蓝色,鼠标离开时为淡蓝色. HTML代码: <button id="submitBtn"  class="btn&quo ...

  6. AngularJS 实战讲义笔记

    第一部分 快速上手 1.1 感受AngularJs四大核心特性(MVC, 模块化,指令系统,双向数据绑定)1.2 搭建自动化的前端开发,调试,测试环境 代码编辑工具 (sublime) 断点调试工具 ...

  7. There is no result type defined for type 'json' mapped with name 'success'. Did you mean 'json'?

    错误信息: 严重: Exception starting filter struts2 Unable to load configuration. - action - file:/C:/Users/ ...

  8. CentOS安装maven3.2.2(Linux系列适用)

    首先,下载最新的maven3.2.2,地址:http://mirrors.cnnic.cn/apache/maven/maven-3/3.2.2/binaries/apache-maven-3.2.2 ...

  9. Euclid gcd规则的证明

    Euclid 规则:如果x和y都是正整数,而且x>=y,那么gcd(x,y)=gcd(x mod y, y) 假设x和y的gcd为a,那么必然有 x=a*n1 y=a*n2(gcd(n1,n2) ...

  10. JVM学习之Eclipse输出GC日志

    Java应用启动时,可以通过设置verbose参数来输出JVM的gc情况,命令如下:-verbose:gc或者-XX:+PrintGC在Eclipse中可以通过Run As|Run Configura ...