高分求VC的Delaunay三角剖分源码

shenl891 2009-03-04 09:42:12
求利用VC编的对于离散的三维数据点进行Delaunay三角剖分的源程序,生长法和逐点插入法都行。算法看过了,只是编程出现问题,请各位高手救救小妹吧,借鉴来修改下,否则无法毕业了呜呜。邮箱shenl301@163.com.
...全文
466 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
AndyZhang 2011-05-10
  • 打赏
  • 举报
回复
请问你能否将能您当年的毕业设计论文和源程序都发给我么您的代码发给我一份,谢谢,正在研究这种算法。谢谢
我的邮箱是734540409@qq.com
lyyiangang 2010-09-08
  • 打赏
  • 举报
回复
好长的程序啊,冒失可以用
roy521 2010-06-24
  • 打赏
  • 举报
回复
需要此算法
hanbin6224 2010-06-24
  • 打赏
  • 举报
回复
请问你能否将能您当年的毕业设计论文和源程序都发给我么您的代码发给我一份,谢谢,正在研究这种算法。谢谢
我的邮箱是350455218@qq.com
hanbin6224 2010-06-24
  • 打赏
  • 举报
回复
请问你能否将能您当年的毕业设计论文和源程序都发给我么您的代码发给我一份,谢谢,正在研究这种算法。谢谢
mishidehuhu 2010-06-03
  • 打赏
  • 举报
回复
同学 能把您当年的毕业设计论文和源程序都发给我么 万分感谢492151869@qq.com
leechrockgames 2009-03-15
  • 打赏
  • 举报
回复
mark
xuegao007 2009-03-08
  • 打赏
  • 举报
回复
mark
linglongyouzhi 2009-03-05
  • 打赏
  • 举报
回复
www.codeguru.com上面有
http://www.codeguru.com/Cpp/data/mfc_database/misc/article.php/c8901/
shenl891 2009-03-05
  • 打赏
  • 举报
回复
为什么没有人呀?呜呜
Hiiishe 2009-03-05
  • 打赏
  • 举报
回复


// Function object to check whether vertex is in circumcircle of triangle.
// operator() returns true if it does.
// The edges of a 'hot' triangle are stored in the edgeSet edges.
class vertexIsInCircumCircle
{
public:
vertexIsInCircumCircle(cvIterator itVertex, edgeSet& edges) : m_itVertex(itVertex), m_Edges(edges) {}
bool operator()(const triangle& tri) const
{
bool b = tri.CCEncompasses(m_itVertex);

if (b)
{
HandleEdge(tri.GetVertex(0), tri.GetVertex(1));
HandleEdge(tri.GetVertex(1), tri.GetVertex(2));
HandleEdge(tri.GetVertex(2), tri.GetVertex(0));
}
return b;
}
protected:
void HandleEdge(const vertex * p0, const vertex * p1) const
{
const vertex * pVertex0(NULL);
const vertex * pVertex1(NULL);

// Create a normalized edge, in which the smallest vertex comes first.
if (* p0 < * p1)
{
pVertex0 = p0;
pVertex1 = p1;
}
else
{
pVertex0 = p1;
pVertex1 = p0;
}

edge e(pVertex0, pVertex1);

// Check if this edge is already in the buffer
edgeIterator found = m_Edges.find(e);

if (found == m_Edges.end()) m_Edges.insert(e); // no, it isn't, so insert
else m_Edges.erase(found); // yes, it is, so erase it to eliminate double edges
}

cvIterator m_itVertex;
edgeSet& m_Edges;
};

void Delaunay::Triangulate(const vertexSet& vertices, triangleSet& output)
{
if (vertices.size() < 3) return; // nothing to handle

// Determine the bounding box.
cvIterator itVertex = vertices.begin();

REAL xMin = itVertex->GetX();
REAL yMin = itVertex->GetY();
REAL xMax = xMin;
REAL yMax = yMin;

++itVertex; // If we're here, we know that vertices is not empty.
for (; itVertex != vertices.end(); itVertex++)
{
xMax = itVertex->GetX(); // Vertices are sorted along the x-axis, so the last one stored will be the biggest.
REAL y = itVertex->GetY();
if (y < yMin) yMin = y;
if (y > yMax) yMax = y;
}

REAL dx = xMax - xMin;
REAL dy = yMax - yMin;

// Make the bounding box slightly bigger, just to feel safe.
REAL ddx = dx * 0.01F;
REAL ddy = dy * 0.01F;

xMin -= ddx;
xMax += ddx;
dx += 2 * ddx;

yMin -= ddy;
yMax += ddy;
dy += 2 * ddy;

// Create a 'super triangle', encompassing all the vertices. We choose an equilateral triangle with horizontal base.
// We could have made the 'super triangle' simply very big. However, the algorithm is quite sensitive to
// rounding errors, so it's better to make the 'super triangle' just big enough, like we do here.
vertex vSuper[3];

vSuper[0] = vertex(xMin - dy * sqrt3 / 3.0F, yMin,0.0F); // Simple highschool geometry, believe me.
vSuper[1] = vertex(xMax + dy * sqrt3 / 3.0F, yMin,0.0F);
vSuper[2] = vertex((xMin + xMax) * 0.5F, yMax + dx * sqrt3 * 0.5F,0.0F);

triangleSet workset;
workset.insert(triangle(vSuper));

for (itVertex = vertices.begin(); itVertex != vertices.end(); itVertex++)
{
// First, remove all 'completed' triangles from the workset.
// A triangle is 'completed' if its circumcircle is entirely to the left of the current vertex.
// Vertices are sorted in x-direction (the set container does this automagically).
// Unless they are part of the 'super triangle', copy the 'completed' triangles to the output.
// The algorithm also works without this step, but it is an important optimalization for bigger numbers of vertices.
// It makes the algorithm about five times faster for 2000 vertices, and for 10000 vertices,
// it's thirty times faster. For smaller numbers, the difference is negligible.
tIterator itEnd = remove_if(workset.begin(), workset.end(), triangleIsCompleted(itVertex, output, vSuper));

edgeSet edges;

// A triangle is 'hot' if the current vertex v is inside the circumcircle.
// Remove all hot triangles, but keep their edges.
itEnd = remove_if(workset.begin(), itEnd, vertexIsInCircumCircle(itVertex, edges));
workset.erase(itEnd, workset.end()); // remove_if doesn't actually remove; we have to do this explicitly.

// Create new triangles from the edges and the current vertex.
for (edgeIterator it = edges.begin(); it != edges.end(); it++)
workset.insert(triangle(it->m_pV0, it->m_pV1, & (* itVertex)));
}

// Finally, remove all the triangles belonging to the 'super triangle' and move the remaining
// triangles tot the output; remove_copy_if lets us do that in one go.
tIterator where = output.begin();
remove_copy_if(workset.begin(), workset.end(), inserter(output, where), triangleHasVertex(vSuper));
}

void Delaunay::TrianglesToEdges(const triangleSet& triangles, edgeSet& edges)
{
for (ctIterator it = triangles.begin(); it != triangles.end(); ++it)
{
HandleEdge(it->GetVertex(0), it->GetVertex(1), edges);
HandleEdge(it->GetVertex(1), it->GetVertex(2), edges);
HandleEdge(it->GetVertex(2), it->GetVertex(0), edges);
}
}

void Delaunay::HandleEdge(const vertex * p0, const vertex * p1, edgeSet& edges)
{
const vertex * pV0(NULL);
const vertex * pV1(NULL);

if (* p0 < * p1)
{
pV0 = p0;
pV1 = p1;
}
else
{
pV0 = p1;
pV1 = p0;
}

// Insert a normalized edge. If it's already in edges, insertion will fail,
// thus leaving only unique edges.
edges.insert(edge(pV0, pV1));
}


Hiiishe 2009-03-05
  • 打赏
  • 举报
回复


//CPP


#include "StdAfx.h"
#include "Delaunay.h"

const REAL sqrt3 = 1.732050808F;

void triangle::SetCircumCircle()
{
REAL x0 = m_Vertices[0]->GetX();
REAL y0 = m_Vertices[0]->GetY();

REAL x1 = m_Vertices[1]->GetX();
REAL y1 = m_Vertices[1]->GetY();

REAL x2 = m_Vertices[2]->GetX();
REAL y2 = m_Vertices[2]->GetY();

REAL y10 = y1 - y0;
REAL y21 = y2 - y1;

bool b21zero = y21 > -REAL_EPSILON && y21 < REAL_EPSILON;

if (y10 > -REAL_EPSILON && y10 < REAL_EPSILON)
{
if (b21zero) // All three vertices are on one horizontal line.
{
if (x1 > x0)
{
if (x2 > x1) x1 = x2;
}
else
{
if (x2 < x0) x0 = x2;
}
m_Center.X = (x0 + x1) * .5F;
m_Center.Y = y0;
}
else // m_Vertices[0] and m_Vertices[1] are on one horizontal line.
{
REAL m1 = - (x2 - x1) / y21;

REAL mx1 = (x1 + x2) * .5F;
REAL my1 = (y1 + y2) * .5F;

m_Center.X = (x0 + x1) * .5F;
m_Center.Y = m1 * (m_Center.X - mx1) + my1;
}
}
else if (b21zero) // m_Vertices[1] and m_Vertices[2] are on one horizontal line.
{
REAL m0 = - (x1 - x0) / y10;

REAL mx0 = (x0 + x1) * .5F;
REAL my0 = (y0 + y1) * .5F;

m_Center.X = (x1 + x2) * .5F;
m_Center.Y = m0 * (m_Center.X - mx0) + my0;
}
else // 'Common' cases, no multiple vertices are on one horizontal line.
{
REAL m0 = - (x1 - x0) / y10;
REAL m1 = - (x2 - x1) / y21;

REAL mx0 = (x0 + x1) * .5F;
REAL my0 = (y0 + y1) * .5F;

REAL mx1 = (x1 + x2) * .5F;
REAL my1 = (y1 + y2) * .5F;

m_Center.X = (m0 * mx0 - m1 * mx1 + my1 - my0) / (m0 - m1);
m_Center.Y = m0 * (m_Center.X - mx0) + my0;
}

REAL dx = x0 - m_Center.X;
REAL dy = y0 - m_Center.Y;

m_R2 = dx * dx + dy * dy; // the radius of the circumcircle, squared
m_R = (REAL) sqrt(m_R2); // the proper radius

// Version 1.1: make m_R2 slightly higher to ensure that all edges
// of co-circular vertices will be caught.
// Note that this is a compromise. In fact, the algorithm isn't really
// suited for very many co-circular vertices.
m_R2 *= 1.000001f;
}

// Function object to check whether a triangle has one of the vertices in SuperTriangle.
// operator() returns true if it does.
class triangleHasVertex
{
public:
triangleHasVertex(const vertex SuperTriangle[3]) : m_pSuperTriangle(SuperTriangle) {}
bool operator()(const triangle& tri) const
{
for (int i = 0; i < 3; i++)
{
const vertex * p = tri.GetVertex(i);
if (p >= m_pSuperTriangle && p < (m_pSuperTriangle + 3)) return true;
}
return false;
}
protected:
const vertex * m_pSuperTriangle;
};

// Function object to check whether a triangle is 'completed', i.e. doesn't need to be checked
// again in the algorithm, i.e. it won't be changed anymore.
// Therefore it can be removed from the workset.
// A triangle is completed if the circumcircle is completely to the left of the current vertex.
// If a triangle is completed, it will be inserted in the output set, unless one or more of it's vertices
// belong to the 'super triangle'.
class triangleIsCompleted
{
public:
triangleIsCompleted(cvIterator itVertex, triangleSet& output, const vertex SuperTriangle[3])
: m_itVertex(itVertex)
, m_Output(output)
, m_pSuperTriangle(SuperTriangle)
{}
bool operator()(const triangle& tri) const
{
bool b = tri.IsLeftOf(m_itVertex);

if (b)
{
triangleHasVertex thv(m_pSuperTriangle);
if (! thv(tri)) m_Output.insert(tri);
}
return b;
}

protected:
cvIterator m_itVertex;
triangleSet& m_Output;
const vertex * m_pSuperTriangle;
};


Hiiishe 2009-03-05
  • 打赏
  • 举报
回复

// 头文件

#pragma once

#include <set>
#include <algorithm>
#include <math.h>

using namespace std;

#ifndef _GDIPLUS_H

// I designed this with GDI+ in mind. However, this particular code doesn't
// use GDI+ at all, only some of it's variable types.
// These definitions are substitutes for those of GDI+.
typedef float REAL;
struct PointF
{
PointF() : X(0), Y(0) {propZ=0;}
PointF(const PointF& p) : X(p.X), Y(p.Y) {propZ=p.propZ;}
PointF(REAL x, REAL y, REAL z) : X(x), Y(y) {propZ=z;}
PointF operator+(const PointF& p) const { return PointF(X + p.X, Y + p.Y, propZ + p.propZ); }
PointF operator-(const PointF& p) const { return PointF(X - p.X, Y - p.Y, propZ - p.propZ); }
REAL X;
REAL Y;
REAL propZ; // 用于等值线的点值,add by zhaoyang.
};

const REAL REAL_EPSILON = 1.192092896e-07F; // = 2^-23; I've no idea why this is a good value, but GDI+ has it.

#endif // _GDIPLUS_H

///////////////////
// vertex

class vertex
{
public:
vertex() : m_Pnt(0.0F, 0.0F, 0.0F) {}
vertex(const vertex& v) : m_Pnt(v.m_Pnt) {}
vertex(const PointF& pnt) : m_Pnt(pnt) {}
vertex(REAL x, REAL y, REAL z) : m_Pnt(x, y, z) {}
vertex(int x, int y, int z) : m_Pnt((REAL) x, (REAL) y, (REAL) z) {}

bool operator<(const vertex& v) const
{
if (m_Pnt.X == v.m_Pnt.X) return m_Pnt.Y < v.m_Pnt.Y;
return m_Pnt.X < v.m_Pnt.X;
}

bool operator==(const vertex& v) const
{
return m_Pnt.X == v.m_Pnt.X && m_Pnt.Y == v.m_Pnt.Y;
}

REAL GetX() const { return m_Pnt.X; }
REAL GetY() const { return m_Pnt.Y; }
REAL GetZ() const { return m_Pnt.propZ;};

void SetX(REAL x) { m_Pnt.X = x; }
void SetY(REAL y) { m_Pnt.Y = y; }
void SetZ(REAL z) { m_Pnt.propZ = z; }

const PointF& GetPoint() const { return m_Pnt; }
protected:
PointF m_Pnt;
};

typedef set<vertex> vertexSet;
typedef set<vertex>::iterator vIterator;
typedef set<vertex>::const_iterator cvIterator;

///////////////////
// triangle

class triangle
{
public:
triangle(const triangle& tri)
: m_Center(tri.m_Center)
, m_R(tri.m_R)
, m_R2(tri.m_R2)
{
for (int i = 0; i < 3; i++) m_Vertices[i] = tri.m_Vertices[i];
}
triangle(const vertex * p0, const vertex * p1, const vertex * p2)
{
m_Vertices[0] = p0;
m_Vertices[1] = p1;
m_Vertices[2] = p2;
SetCircumCircle();
}
triangle(const vertex * pV)
{
for (int i = 0; i < 3; i++) m_Vertices[i] = pV++;
SetCircumCircle();
}

bool operator<(const triangle& tri) const
{
if (m_Center.X == tri.m_Center.X) return m_Center.Y < tri.m_Center.Y;
return m_Center.X < tri.m_Center.X;
}

const vertex * GetVertex(int i) const
{
ASSERT(i >= 0);
ASSERT(i < 3);
return m_Vertices[i];
}

bool IsLeftOf(cvIterator itVertex) const
{
// returns true if * itVertex is to the right of the triangle's circumcircle
return itVertex->GetPoint().X > (m_Center.X + m_R);
}

bool CCEncompasses(cvIterator itVertex) const
{
// Returns true if * itVertex is in the triangle's circumcircle.
// A vertex exactly on the circle is also considered to be in the circle.

// These next few lines look like optimisation, however in practice they are not.
// They even seem to slow down the algorithm somewhat.
// Therefore, I've commented them out.

// First check boundary box.
// REAL x = itVertex->GetPoint().X;
//
// if (x > (m_Center.X + m_R)) return false;
// if (x < (m_Center.X - m_R)) return false;
//
// REAL y = itVertex->GetPoint().Y;
//
// if (y > (m_Center.Y + m_R)) return false;
// if (y < (m_Center.Y - m_R)) return false;

PointF dist = itVertex->GetPoint() - m_Center; // the distance between v and the circle center
REAL dist2 = dist.X * dist.X + dist.Y * dist.Y; // squared
return dist2 <= m_R2; // compare with squared radius
}
protected:
const vertex * m_Vertices[3]; // the three triangle vertices
PointF m_Center; // center of circumcircle
REAL m_R; // radius of circumcircle
REAL m_R2; // radius of circumcircle, squared

void SetCircumCircle();
};

// Changed in verion 1.1: collect triangles in a multiset.
// In version 1.0, I used a set, preventing the creation of multiple
// triangles with identical center points. Therefore, more than three
// co-circular vertices yielded incorrect results. Thanks to Roger Labbe.
typedef multiset<triangle> triangleSet;
typedef multiset<triangle>::iterator tIterator;
typedef multiset<triangle>::const_iterator ctIterator;

///////////////////
// edge

class edge
{
public:
edge(const edge& e) : m_pV0(e.m_pV0), m_pV1(e.m_pV1) {}
edge(const vertex * pV0, const vertex * pV1)
: m_pV0(pV0), m_pV1(pV1)
{
}

bool operator<(const edge& e) const
{
if (m_pV0 == e.m_pV0) return * m_pV1 < * e.m_pV1;
return * m_pV0 < * e.m_pV0;
}

const vertex * m_pV0;
const vertex * m_pV1;
};

typedef set<edge> edgeSet;
typedef set<edge>::iterator edgeIterator;
typedef set<edge>::const_iterator cedgeIterator;

///////////////////
// Delaunay

class Delaunay
{
public:
// Calculate the Delaunay triangulation for the given set of vertices.
void Triangulate(const vertexSet& vertices, triangleSet& output);

// Put the edges of the triangles in an edgeSet, eliminating double edges.
// This comes in useful for drawing the triangulation.
void TrianglesToEdges(const triangleSet& triangles, edgeSet& edges);
protected:
void HandleEdge(const vertex * p0, const vertex * p1, edgeSet& edges);
};

Hiiishe 2009-03-05
  • 打赏
  • 举报
回复
http://topic.csdn.net/u/20090226/15/4ceaa537-c87e-44f0-8def-6e937b7fca35.html
有我回复过的
shenl891 2009-03-04
  • 打赏
  • 举报
回复
没人理我哦?自己顶下呜呜
shenl891 2009-03-04
  • 打赏
  • 举报
回复
程序流程图也行呀!!!

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧