Main Page   Namespace List   Class Hierarchy   Compound List   File List   Header Files   Sources   Namespace Members   Compound Members   File Members  

delaunay.cpp

00001 //$Header: /home/ben/Mapper/c++/RCS/delaunay.cpp,v 6.8 2002/06/14 22:28:47 ben Exp $
00002 // Copyright Benedict Adamson 2002.
00003 // This file is part of Mapper.
00004 
00005 // Mapper is free software; you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation; either version 2 of the License, or
00008 // (at your option) any later version.
00009 
00010 // Mapper is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 
00015 // You should have received a copy of the GNU General Public License
00016 // along with Mapper; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 
00029 #include <algorithm>
00030 #include <cassert>
00031 #include <cstdlib>
00032 
00033 #include "delaunay.h"
00034 #include "matrix2x2.h"
00035 
00036 
00037 
00038 delaunay::triangle::triangle(
00039    const vector2 &v0,
00040    const vector2 &v1,
00041    const vector2 &v2
00042    )
00043 {
00044    this->vertex_[0] = v0;
00045    this->vertex_[1] = v1;
00046    this->vertex_[2] = v2;
00047    this->calculate_circumcircle();
00048    {//Postconditions:
00049       assert( this->vertex(0) == v0 );
00050       assert( this->vertex(1) == v1 );
00051       assert( this->vertex(2) == v2 );
00052    };
00053 };
00054 
00055 
00056 
00057 delaunay::triangle::triangle(
00058    const delaunay::triangle::triangle &t
00059    )
00060    :
00061    circumcentre_( t.circumcentre_ ),
00062    circumradius2( t.circumradius2 )
00063 {
00064    this->vertex_[0] = t.vertex_[0];
00065    this->vertex_[1] = t.vertex_[1];
00066    this->vertex_[2] = t.vertex_[2];
00067 }
00068 
00069 const double delaunay::triangle::circumradius(void) const
00070 {
00071    return sqrt(this->circumradius2);
00072 }
00073 
00074 
00075 
00076 bool delaunay::triangle::circumcircle_contains(
00077    const vector2 &p
00078    ) const
00079 {
00080    const vector2 rp( p - this->circumcentre_ );
00081    return rp*rp <= this->circumradius2;
00082 }
00083 
00084 
00085 
00086 void delaunay::triangle::calculate_circumcircle(void)
00087 {
00088    const vector2 &v0( this->vertex(0) );
00089    const vector2 &v1( this->vertex(1) );
00090    const vector2 &v2( this->vertex(2) );
00091    {//Calculate the circumcentre
00092       const vector2 d01( v1 - v0 );
00093       const vector2 d02( v2 - v0 );
00094       const vector2 d12( v2 - v1 );
00095       const vector2 m01( 0.5*(v0 + v1) );
00096       const vector2 m02( 0.5*(v0 + v2) );
00097       const vector2 r01( -d01.y, d01.x );
00098       const vector2 r02( -d02.y, d02.x );
00099       const matrix2x2 M(
00100          r01.x, d02.y,
00101          d01.x, -r02.y
00102          );
00103       const vector2 y( 0.5*d12 );
00104       const vector2 a( matrix2x2::solve( M, y ) );
00105       const vector2 c01 = m01 + a[0] * r01;
00106       const vector2 c02 = m02 + a[1] * r02;
00107       this->circumcentre_ = 0.5*(c01 + c02);
00108    };
00109    {//Calculate the square of the circumradius
00110       const vector2 r0 = v0 - this->circumcentre_;
00111       this->circumradius2 = r0*r0;
00112    };
00113 }
00114 
00115 
00116 
00117 delaunay::triangulation::triangulation(
00118    const double l,
00119    const double r,
00120    const double t,
00121    const double b
00122    )
00123    :
00124    left( l ),
00125    right( r ),
00126    top( t ),
00127    bottom( b ),
00128    tl( l, t ),
00129    tr( r, t ),
00130    br( r, b ),
00131    bl( l, b )
00132 {
00133    this->triangles_.reserve( 2 );
00134    this->triangles_.push_back( triangle( tl, tr, bl ) );
00135    this->triangles_.push_back( triangle( bl, tr, br ) );
00136 }
00137 
00138 
00139 
00140 delaunay::triangulation::~triangulation(void)
00141 {
00142    //Do nothing
00143 }
00144 
00145 
00146 
00147 void delaunay::triangulation::add_point(
00148    const vector2 &p
00149    )
00150 {
00151    {//Preconditions:
00152       assert( this->left <= p.x && p.x <= this->right );
00153       assert( this->bottom <= p.y && p.y <= this->top );
00154       assert( !this->contains( p ) );
00155    };
00156    vector< delaunay::triangle > new_triangles;
00157    vector< delaunay::edge > edges;
00158    {//heuristic: reserve space
00159       static const unsigned expected_intersect = 10u;
00160       new_triangles.reserve( this->triangles_.size() + expected_intersect );
00161       edges.reserve( expected_intersect * 3u );
00162    };
00163    for( vector< delaunay::triangle >::iterator i = this->triangles_.begin();
00164         i != this->triangles_.end();
00165         i++ ){//scan existing triangles
00166       if( (*i).circumcircle_contains( p ) ){
00167          //triangle will be changed
00168          edges.push_back( edge( (*i).vertex(0), (*i).vertex(1) ) );
00169          edges.push_back( edge( (*i).vertex(1), (*i).vertex(2) ) );
00170          edges.push_back( edge( (*i).vertex(2), (*i).vertex(0) ) );
00171       }else{
00172          //triangle not changed
00173          new_triangles.push_back( *i );
00174       };
00175    };
00176    {//eliminate edges that are duplicated
00177       vector< delaunay::edge > new_edges;
00178       new_edges.reserve( edges.size() ); //heuristic
00179       vector< delaunay::edge >::iterator begin = edges.begin();
00180       vector< delaunay::edge >::iterator end = edges.end();
00181       for( vector< delaunay::edge >::iterator i = begin;
00182            i != end;
00183            i++ ){
00184          edge &e( *i );
00185          bool duplicate = false;
00186          {//determine whether duplicate
00187             //Not efficient, but N is usually small
00188             vector< delaunay::edge >::iterator j = begin;
00189             while( !duplicate && j != end ){
00190                if( j != i ){
00191                   duplicate = (e == *j);
00192                };//else skip self
00193                j++;
00194             };
00195          };
00196          if( !duplicate ){
00197             new_edges.push_back( e );
00198          };
00199       };
00200       edges.swap( new_edges );
00201    };
00202    {//create the new triangles
00203       for( vector< delaunay::edge >::iterator i = edges.begin();
00204            i != edges.end();
00205            i++ ){
00206          edge &e( *i );
00207          new_triangles.push_back(
00208             triangle( e.vertex(0), e.vertex(1), p )
00209             );
00210       };
00211    }
00212    this->triangles_.swap( new_triangles );
00213    {//Postconditions:
00214       assert( this->contains( p ) );
00215    };
00216 }
00217 
00218 
00219 
00220 bool delaunay::triangulation::contains(
00221    const vector2 &p
00222    ) const
00223 {
00224    //assert( this->contains( this->tl ) );
00225    //assert( this->contains( this->tr ) );
00226    //assert( this->contains( this->br ) );
00227    //assert( this->contains( this->bl ) );
00228    //Indicates whether the given point is a vertex
00229    //of any of the traingles of the triangulation.
00230    register bool c = false;
00231    vector< triangle >::const_iterator i = this->triangles_.begin();
00232    const vector< triangle >::const_iterator end = this->triangles_.end();
00233    while( !c && i != end ){
00234       const triangle &t( *i );
00235       c = (t.vertex(0) == p) ||
00236          (t.vertex(1) == p ) ||
00237          (t.vertex(2) == p);
00238       i++;
00239    };
00240    return c;
00241 }

Generated at Sun Jul 14 20:38:07 2002 for Mapper by doxygen 1.0.0 written by Dimitri van Heesch, © 1997-1999