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

📄 delaunay.h.svn-base

📁 坦克大战游戏完整全套源代码
💻 SVN-BASE
字号:
/********************************************************************************
Copyright (C) 2004-2005 Sjaak Priester	

This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this application; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
********************************************************************************/

// Delaunay
// Class to perform Delaunay triangulation on a set of vertices
//
// Version 1.2 (C) 2005, Sjaak Priester, Amsterdam.
// - Removed stupid bug in SetY; function wasn't used, so no consequences. Thanks to squat.
//
// Version 1.1 (C) 2005, Sjaak Priester, Amsterdam.
// - Removed bug which gave incorrect results for co-circular vertices.
//
// Version 1.0 (C) 2004, Sjaak Priester, Amsterdam.
// mailto:sjaak@sjaakpriester.nl

#pragma once

#include <cassert>
#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)	{}
    PointF(const PointF& p) : X(p.X), Y(p.Y)	{}
    PointF(REAL x, REAL y) : X(x), Y(y)	{}
    PointF operator+(const PointF& p) const	{ return PointF(X + p.X, Y + p.Y); }
    PointF operator-(const PointF& p) const	{ return PointF(X - p.X, Y - p.Y); }
    REAL X;
    REAL Y;
};

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), userData(0)         {}
    vertex(const vertex& v)		: m_Pnt(v.m_Pnt), userData(v.userData)   {}
    vertex(const PointF& pnt)	: m_Pnt(pnt), userData(0)				 {}
    vertex(REAL x, REAL y)		: m_Pnt(x, y), userData(0)				 {}
    vertex(int x, int y)		: m_Pnt((REAL) x, (REAL) y), userData(0) {}

    void setUserData(size_t ud)
    {
        userData = ud;
    }

    size_t getUserData() const
    {
        return userData;
    }

    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; }

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

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

typedef set<vertex> vertexSet;
typedef vertexSet::iterator vIterator;
typedef vertexSet::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> triangleSet;
typedef triangleSet::iterator tIterator;
typedef triangleSet::const_iterator ctIterator;

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

class edge
{
public:
    edge(const edge& e)	: m_pV0(e.m_pV0), m_pV1(e.m_pV1), t0(e.t0), t1(e.t1)	{}
    edge(const vertex * pV0, const vertex * pV1)
        : m_pV0(pV0), m_pV1(pV1), t0(size_t(-1)), t1(size_t(-1))
    {
    }

    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;
    mutable size_t t0, t1;
};

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

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

class Delaunay
{
public:
    // Calculate the Delaunay triangulation for the given set of vertices.
    static 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.
    static void TrianglesToEdges(const triangleSet& triangles, edgeSet& edges);
protected:
    static void HandleEdge(const vertex * p0, const vertex * p1, edgeSet& edges, size_t triangleId);
};

⌨️ 快捷键说明

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