[GRASS-SVN] r29881 - grass/trunk/vector/v.hull
svn_grass at osgeo.org
svn_grass at osgeo.org
Mon Jan 28 08:56:00 EST 2008
Author: neteler
Date: 2008-01-28 08:56:00 -0500 (Mon, 28 Jan 2008)
New Revision: 29881
Added:
grass/trunk/vector/v.hull/chull.c
grass/trunk/vector/v.hull/chull.h
grass/trunk/vector/v.hull/globals.h
grass/trunk/vector/v.hull/macros.h
Modified:
grass/trunk/vector/v.hull/README
Log:
Benjamin Ducke: <benjamin.ducke ufg.uni-kiel.de> 3D hull support added using chull.c from Joseph O'Rourke, 1998
Modified: grass/trunk/vector/v.hull/README
===================================================================
--- grass/trunk/vector/v.hull/README 2008-01-28 13:44:17 UTC (rev 29880)
+++ grass/trunk/vector/v.hull/README 2008-01-28 13:56:00 UTC (rev 29881)
@@ -12,3 +12,9 @@
Andrea Aime <aaime at libero.it> 9/2001
+
+-----------------
+chull.c
+http://maven.smith.edu/~orourke/books/compgeom.html
+http://maven.smith.edu/~orourke/books/ftp.html
+
Added: grass/trunk/vector/v.hull/chull.c
===================================================================
--- grass/trunk/vector/v.hull/chull.c (rev 0)
+++ grass/trunk/vector/v.hull/chull.c 2008-01-28 13:56:00 UTC (rev 29881)
@@ -0,0 +1,785 @@
+/*
+This code is described in "Computational Geometry in C" (Second Edition),
+Chapter 4. It is not written to be comprehensible without the
+explanation in that book.
+
+Input: 3n integer coordinates for the points.
+Output: the 3D convex hull, in postscript with embedded comments
+ showing the vertices and faces.
+
+Compile: gcc -o chull chull.c
+
+Written by Joseph O'Rourke, with contributions by
+ Kristy Anderson, John Kutcher, Catherine Schevon, Susan Weller.
+Last modified: March 1998
+Questions to orourke at cs.smith.edu.
+--------------------------------------------------------------------
+This code is Copyright 1998 by Joseph O'Rourke. It may be freely
+redistributed in its entirety provided that this copyright notice is
+not removed.
+--------------------------------------------------------------------
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include <grass/gis.h>
+#include <grass/Vect.h>
+
+#include "globals.h"
+
+/*Define Boolean type */
+typedef enum { BFALSE, BTRUE } bool;
+
+/* Define vertex indices. */
+#define X 0
+#define Y 1
+#define Z 2
+
+/* Define structures for vertices, edges and faces */
+typedef struct tVertexStructure tsVertex;
+typedef tsVertex *tVertex;
+
+typedef struct tEdgeStructure tsEdge;
+typedef tsEdge *tEdge;
+
+typedef struct tFaceStructure tsFace;
+typedef tsFace *tFace;
+
+struct tVertexStructure {
+ double v[3];
+ int vnum;
+ tEdge duplicate; /* pointer to incident cone edge (or NULL) */
+ bool onhull; /* T iff point on hull. */
+ bool mark; /* T iff point already processed. */
+ tVertex next, prev;
+};
+
+struct tEdgeStructure {
+ tFace adjface[2];
+ tVertex endpts[2];
+ tFace newface; /* pointer to incident cone face. */
+ bool delete; /* T iff edge should be delete. */
+ tEdge next, prev;
+};
+
+struct tFaceStructure {
+ tEdge edge[3];
+ tVertex vertex[3];
+ bool visible; /* T iff face visible from new point. */
+ tFace next, prev;
+};
+
+/* Define flags */
+#define ONHULL BTRUE
+#define REMOVED BTRUE
+#define VISIBLE BTRUE
+#define PROCESSED BTRUE
+
+/* Global variable definitions */
+tVertex vertices = NULL;
+tEdge edges = NULL;
+tFace faces = NULL;
+
+/* Function declarations */
+tVertex MakeNullVertex( void );
+void ReadVertices( double *px, double *py, double *pz, int num_points);
+void writeVertices ( struct Map_info *Map );
+int DoubleTriangle( void );
+void ConstructHull( void );
+bool AddOne( tVertex p );
+int VolumeSign(tFace f, tVertex p);
+tFace MakeConeFace( tEdge e, tVertex p );
+void MakeCcw( tFace f, tEdge e, tVertex p );
+tEdge MakeNullEdge( void );
+tFace MakeNullFace( void );
+tFace MakeFace( tVertex v0, tVertex v1, tVertex v2, tFace f );
+void CleanUp( void );
+void CleanEdges( void );
+void CleanFaces( void );
+void CleanVertices( void );
+bool Collinear( tVertex a, tVertex b, tVertex c );
+
+#include "macros.h"
+
+
+/*
+
+ Release all memory allocated for edges, faces and vertices
+
+*/
+void freeMem ( void ) {
+ tEdge e; /* Primary index into edge list. */
+ tFace f; /* Primary pointer into face list. */
+ tVertex v;
+ tEdge te; /* Temporary edge pointer. */
+ tFace tf; /* Temporary face pointer. */
+ tVertex tv; /* Temporary vertex pointer. */
+
+ e = edges;
+ do {
+ te = e;
+ e = e->next;
+ DELETE( edges, te );
+ } while ( e != edges );
+
+ f = faces;
+ do {
+ tf = f;
+ f = f->next;
+ DELETE( faces, tf );
+ } while ( f != faces );
+
+ v = vertices;
+ do {
+ tv = v;
+ v = v->next;
+ DELETE( vertices, tv );
+ } while ( v != vertices );
+
+ FREE (te);
+ FREE (tf);
+ FREE (tv);
+
+ DELETE (edges, e);
+ DELETE (faces, f);
+ DELETE (vertices, v);
+
+ FREE (edges);
+ FREE (faces);
+ FREE (vertices);
+
+}
+
+
+/*-------------------------------------------------------------------*/
+int make3DHull ( double *px, double *py, double *pz, int num_points, struct Map_info *Map )
+{
+ int error;
+
+ ReadVertices( px, py, pz, num_points );
+
+ error = DoubleTriangle();
+ if ( error < 0 ) {
+ G_fatal_error ( "All points of 3D input map are in the same plane.\n Cannot create a 3D hull." );
+ }
+
+ ConstructHull();
+
+ writeVertices ( Map );
+
+ freeMem ();
+
+ return (0);
+}
+
+/*---------------------------------------------------------------------
+MakeNullVertex: Makes a vertex, nulls out fields.
+---------------------------------------------------------------------*/
+tVertex MakeNullVertex( void )
+{
+ tVertex v;
+
+ NEW( v, tsVertex );
+ v->duplicate = NULL;
+ v->onhull = !ONHULL;
+ v->mark = !PROCESSED;
+ ADD( vertices, v );
+
+ return v;
+}
+
+/*---------------------------------------------------------------------
+ReadVertices: Reads in the vertices, and links them into a circular
+list with MakeNullVertex. There is no need for the # of vertices to be
+the first line: the function looks for EOF instead. Sets the global
+variable vertices via the ADD macro.
+---------------------------------------------------------------------*/
+void ReadVertices( double *px, double *py, double *pz, int num_points )
+{
+ tVertex v;
+ int vnum = 0;
+ int i;
+
+ G_message ( "Reading 3D vertices:" );
+
+ for ( i=0; i < num_points; i++ ) {
+ v = MakeNullVertex();
+ v->v[X] = px[i];
+ v->v[Y] = py[i];
+ v->v[Z] = pz[i];
+ v->vnum = vnum++;
+ G_percent (i, (num_points-1), 1);
+ }
+ fflush (stdout);
+}
+
+
+/*---------------------------------------------------------------------
+Outputs the 3D triangles to a GRASS 3d vector map.
+---------------------------------------------------------------------*/
+void writeVertices ( struct Map_info *Map )
+{
+ /* Pointers to vertices, edges, faces. */
+ tVertex v;
+ tEdge e;
+ tFace f;
+ double *px,*py,*pz;
+ double fx,fy,fz;
+ double kx, ky, kz;
+
+ long int cat, num_faces;
+
+ struct line_pnts *Points;
+ struct line_cats *Cats;
+
+
+ Points = Vect_new_line_struct ();
+ Cats = Vect_new_cats_struct ();
+
+ px = G_malloc ( sizeof (double) * 4);
+ py = G_malloc ( sizeof (double) * 4);
+ pz = G_malloc ( sizeof (double) * 4);
+
+ f = faces;
+ num_faces = 0;
+ cat = 0;
+ kx = 0.0;
+ ky = 0.0;
+ kz = 0.0;
+
+ G_message ( "Writing faces and kernel to output map ..." );
+
+ do {
+
+ num_faces ++;
+
+ /* write one triangular face */
+ px[0] = ((double) ( f->vertex[0]->v[X] ) );
+ py[0] = ((double) ( f->vertex[0]->v[Y] ) );
+ pz[0] = ((double) ( f->vertex[0]->v[Z] ) );
+
+ px[1] = ((double) ( f->vertex[1]->v[X] ) );
+ py[1] = ((double) ( f->vertex[1]->v[Y] ) );
+ pz[1] = ((double) ( f->vertex[1]->v[Z] ) );
+
+ px[2] = ((double) ( f->vertex[2]->v[X] ) );
+ py[2] = ((double) ( f->vertex[2]->v[Y] ) );
+ pz[2] = ((double) ( f->vertex[2]->v[Z] ) );
+
+ px[3] = ((double) ( f->vertex[0]->v[X] ) );
+ py[3] = ((double) ( f->vertex[0]->v[Y] ) );
+ pz[3] = ((double) ( f->vertex[0]->v[Z] ) );
+
+ /* kernel position: 1st get 3D center of this face */
+ fx = ( px[0] + px[1] + px[2] ) / 3.0;
+ fy = ( py[0] + py[1] + py[2] ) / 3.0;
+ fz = ( pz[0] + pz[1] + pz[2] ) / 3.0;
+
+ /* kernel position: now add this to kernel coordinates */
+ kx = kx + fx;
+ ky = ky + fy;
+ kz = kz + fz;
+
+ /* write out face */
+ Vect_copy_xyz_to_pnts(Points, px, py, pz, 4);
+ cat ++;
+ Vect_cat_set ( Cats, 1, cat );
+ Vect_write_line ( Map, GV_FACE, Points, Cats );
+
+ f = f->next;
+
+ } while ( f != faces );
+
+ /* write kernel for the center of the whole hull */
+ kx = kx / num_faces;
+ ky = ky / num_faces;
+ kz = kz / num_faces;
+ Vect_cat_set ( Cats, 1, cat + 1 );
+ Vect_copy_xyz_to_pnts(Points, &kx, &ky, &kz, 1);
+ Vect_write_line ( Map, GV_KERNEL, Points, Cats );
+
+ Vect_destroy_line_struct (Points);
+
+ fflush ( stdout );
+
+ G_free (px);
+ G_free (py);
+ G_free (pz);
+
+}
+
+
+/*---------------------------------------------------------------------
+ DoubleTriangle builds the initial double triangle. It first finds 3
+ noncollinear points and makes two faces out of them, in opposite order.
+ It then finds a fourth point that is not coplanar with that face. The
+ vertices are stored in the face structure in counterclockwise order so
+ that the volume between the face and the point is negative. Lastly, the
+ 3 newfaces to the fourth point are constructed and the data structures
+ are cleaned up.
+---------------------------------------------------------------------*/
+
+/* RETURN: 0 if OK */
+/* -1 if all points collinear */
+/* -2 if all points coplanar */
+
+int DoubleTriangle( void )
+{
+ tVertex v0, v1, v2, v3, t;
+ tFace f0, f1 = NULL;
+ tEdge e0, e1, e2, s;
+ long int vol;
+
+ /* Find 3 noncollinear points. */
+ v0 = vertices;
+ while ( Collinear( v0, v0->next, v0->next->next ) ) {
+ if ( ( v0 = v0->next ) == vertices ) {
+ G_warning ("DoubleTriangle: All points are collinear!\n");
+ return (-1);
+ }
+ }
+ v1 = v0->next;
+ v2 = v1->next;
+
+ /* Mark the vertices as processed. */
+ v0->mark = PROCESSED;
+ v1->mark = PROCESSED;
+ v2->mark = PROCESSED;
+
+ /* Create the two "twin" faces. */
+ f0 = MakeFace( v0, v1, v2, f1 );
+ f1 = MakeFace( v2, v1, v0, f0 );
+
+ /* Link adjacent face fields. */
+ f0->edge[0]->adjface[1] = f1;
+ f0->edge[1]->adjface[1] = f1;
+ f0->edge[2]->adjface[1] = f1;
+ f1->edge[0]->adjface[1] = f0;
+ f1->edge[1]->adjface[1] = f0;
+ f1->edge[2]->adjface[1] = f0;
+
+ /* Find a fourth, noncoplanar point to form tetrahedron. */
+ v3 = v2->next;
+ vol = VolumeSign( f0, v3 );
+ while ( !vol ) {
+ if ( ( v3 = v3->next ) == v0 ) {
+ G_warning ("DoubleTriangle: All points are coplanar!\n");
+ return (-2);
+ }
+ vol = VolumeSign( f0, v3 );
+ }
+
+ /* Insure that v3 will be the first added. */
+ vertices = v3;
+
+ return (0);
+}
+
+
+/*---------------------------------------------------------------------
+ConstructHull adds the vertices to the hull one at a time. The hull
+vertices are those in the list marked as onhull.
+---------------------------------------------------------------------*/
+void ConstructHull( void )
+{
+ tVertex v, vnext;
+ long int vol;
+ bool changed; /* T if addition changes hull; not used. */
+ int i;
+ int numVertices;
+
+
+ G_message ("Constructing 3D hull:");
+
+
+ v = vertices;
+ i = 0;
+ do {
+ vnext = v->next;
+ v = vnext;
+ i ++;
+ } while ( v != vertices );
+ numVertices = i;
+
+ v = vertices;
+ i = 0;
+ do {
+ vnext = v->next;
+ if ( !v->mark ) {
+ v->mark = PROCESSED;
+ changed = AddOne( v );
+ CleanUp();
+ }
+ v = vnext;
+ i ++;
+
+ G_percent (i, numVertices, 1);
+
+ } while ( v != vertices );
+
+ fflush (stdout);
+
+}
+
+/*---------------------------------------------------------------------
+AddOne is passed a vertex. It first determines all faces visible from
+that point. If none are visible then the point is marked as not
+onhull. Next is a loop over edges. If both faces adjacent to an edge
+are visible, then the edge is marked for deletion. If just one of the
+adjacent faces is visible then a new face is constructed.
+---------------------------------------------------------------------*/
+bool AddOne( tVertex p )
+{
+ tFace f;
+ tEdge e, temp;
+ long int vol;
+ bool vis = BFALSE;
+
+
+ /* Mark faces visible from p. */
+ f = faces;
+ do {
+ vol = VolumeSign( f, p );
+
+ if ( vol < 0 ) {
+ f->visible = VISIBLE;
+ vis = BTRUE;
+ }
+ f = f->next;
+ } while ( f != faces );
+
+ /* If no faces are visible from p, then p is inside the hull. */
+ if ( !vis ) {
+ p->onhull = !ONHULL;
+ return BFALSE;
+ }
+
+ /* Mark edges in interior of visible region for deletion.
+ Erect a newface based on each border edge. */
+ e = edges;
+ do {
+ temp = e->next;
+ if ( e->adjface[0]->visible && e->adjface[1]->visible )
+ /* e interior: mark for deletion. */
+ e->delete = REMOVED;
+ else if ( e->adjface[0]->visible || e->adjface[1]->visible )
+ /* e border: make a new face. */
+ e->newface = MakeConeFace( e, p );
+ e = temp;
+ } while ( e != edges );
+ return BTRUE;
+}
+
+/*---------------------------------------------------------------------
+VolumeSign returns the sign of the volume of the tetrahedron determined by f
+and p. VolumeSign is +1 iff p is on the negative side of f,
+where the positive side is determined by the rh-rule. So the volume
+is positive if the ccw normal to f points outside the tetrahedron.
+The final fewer-multiplications form is due to Bob Williamson.
+---------------------------------------------------------------------*/
+int VolumeSign( tFace f, tVertex p )
+{
+ double vol;
+ double ax, ay, az, bx, by, bz, cx, cy, cz;
+
+ ax = f->vertex[0]->v[X] - p->v[X];
+ ay = f->vertex[0]->v[Y] - p->v[Y];
+ az = f->vertex[0]->v[Z] - p->v[Z];
+ bx = f->vertex[1]->v[X] - p->v[X];
+ by = f->vertex[1]->v[Y] - p->v[Y];
+ bz = f->vertex[1]->v[Z] - p->v[Z];
+ cx = f->vertex[2]->v[X] - p->v[X];
+ cy = f->vertex[2]->v[Y] - p->v[Y];
+ cz = f->vertex[2]->v[Z] - p->v[Z];
+
+ vol = ax * (by*cz - bz*cy)
+ + ay * (bz*cx - bx*cz)
+ + az * (bx*cy - by*cx);
+
+ /* The volume should be an integer. */
+ if ( vol > 0.0 ) return 1;
+ else if ( vol < -0.0 ) return -1;
+ else return 0;
+}
+
+
+/*---------------------------------------------------------------------
+MakeConeFace makes a new face and two new edges between the
+edge and the point that are passed to it. It returns a pointer to
+the new face.
+---------------------------------------------------------------------*/
+tFace MakeConeFace( tEdge e, tVertex p )
+{
+ tEdge new_edge[2];
+ tFace new_face;
+ int i, j;
+
+ /* Make two new edges (if don't already exist). */
+ for ( i=0; i < 2; ++i )
+ /* If the edge exists, copy it into new_edge. */
+ if ( !( new_edge[i] = e->endpts[i]->duplicate) ) {
+ /* Otherwise (duplicate is NULL), MakeNullEdge. */
+ new_edge[i] = MakeNullEdge();
+ new_edge[i]->endpts[0] = e->endpts[i];
+ new_edge[i]->endpts[1] = p;
+ e->endpts[i]->duplicate = new_edge[i];
+ }
+
+ /* Make the new face. */
+ new_face = MakeNullFace();
+ new_face->edge[0] = e;
+ new_face->edge[1] = new_edge[0];
+ new_face->edge[2] = new_edge[1];
+ MakeCcw( new_face, e, p );
+
+ /* Set the adjacent face pointers. */
+ for ( i=0; i < 2; ++i )
+ for ( j=0; j < 2; ++j )
+ /* Only one NULL link should be set to new_face. */
+ if ( !new_edge[i]->adjface[j] ) {
+ new_edge[i]->adjface[j] = new_face;
+ break;
+ }
+
+ return new_face;
+}
+
+/*---------------------------------------------------------------------
+MakeCcw puts the vertices in the face structure in counterclock wise
+order. We want to store the vertices in the same
+order as in the visible face. The third vertex is always p.
+---------------------------------------------------------------------*/
+void MakeCcw( tFace f, tEdge e, tVertex p )
+{
+ tFace fv; /* The visible face adjacent to e */
+ int i; /* Index of e->endpoint[0] in fv. */
+ tEdge s; /* Temporary, for swapping */
+
+ if ( e->adjface[0]->visible )
+ fv = e->adjface[0];
+ else fv = e->adjface[1];
+
+ /* Set vertex[0] & [1] of f to have the same orientation
+ as do the corresponding vertices of fv. */
+ for ( i=0; fv->vertex[i] != e->endpts[0]; ++i )
+ ;
+ /* Orient f the same as fv. */
+ if ( fv->vertex[ (i+1) % 3 ] != e->endpts[1] ) {
+ f->vertex[0] = e->endpts[1];
+ f->vertex[1] = e->endpts[0];
+ }
+ else {
+ f->vertex[0] = e->endpts[0];
+ f->vertex[1] = e->endpts[1];
+ SWAP( s, f->edge[1], f->edge[2] );
+ }
+ /* This swap is tricky. e is edge[0]. edge[1] is based on endpt[0],
+ edge[2] on endpt[1]. So if e is oriented "forwards," we
+ need to move edge[1] to follow [0], because it precedes. */
+
+ f->vertex[2] = p;
+}
+
+/*---------------------------------------------------------------------
+MakeNullEdge creates a new cell and initializes all pointers to NULL
+and sets all flags to off. It returns a pointer to the empty cell.
+---------------------------------------------------------------------*/
+tEdge MakeNullEdge( void )
+{
+ tEdge e;
+
+ NEW( e, tsEdge );
+ e->adjface[0] = e->adjface[1] = e->newface = NULL;
+ e->endpts[0] = e->endpts[1] = NULL;
+ e->delete = !REMOVED;
+ ADD( edges, e );
+ return e;
+}
+
+/*--------------------------------------------------------------------
+MakeNullFace creates a new face structure and initializes all of its
+flags to NULL and sets all the flags to off. It returns a pointer
+to the empty cell.
+---------------------------------------------------------------------*/
+tFace MakeNullFace( void )
+{
+ tFace f;
+ int i;
+
+ NEW( f, tsFace);
+ for ( i=0; i < 3; ++i ) {
+ f->edge[i] = NULL;
+ f->vertex[i] = NULL;
+ }
+ f->visible = !VISIBLE;
+ ADD( faces, f );
+ return f;
+}
+
+/*---------------------------------------------------------------------
+MakeFace creates a new face structure from three vertices (in ccw
+order). It returns a pointer to the face.
+---------------------------------------------------------------------*/
+tFace MakeFace( tVertex v0, tVertex v1, tVertex v2, tFace fold )
+{
+ tFace f;
+ tEdge e0, e1, e2;
+
+ /* Create edges of the initial triangle. */
+ if( !fold ) {
+ e0 = MakeNullEdge();
+ e1 = MakeNullEdge();
+ e2 = MakeNullEdge();
+ }
+ else { /* Copy from fold, in reverse order. */
+ e0 = fold->edge[2];
+ e1 = fold->edge[1];
+ e2 = fold->edge[0];
+ }
+ e0->endpts[0] = v0; e0->endpts[1] = v1;
+ e1->endpts[0] = v1; e1->endpts[1] = v2;
+ e2->endpts[0] = v2; e2->endpts[1] = v0;
+
+ /* Create face for triangle. */
+ f = MakeNullFace();
+ f->edge[0] = e0; f->edge[1] = e1; f->edge[2] = e2;
+ f->vertex[0] = v0; f->vertex[1] = v1; f->vertex[2] = v2;
+
+ /* Link edges to face. */
+ e0->adjface[0] = e1->adjface[0] = e2->adjface[0] = f;
+
+ return f;
+}
+
+/*---------------------------------------------------------------------
+CleanUp goes through each data structure list and clears all
+flags and NULLs out some pointers. The order of processing
+(edges, faces, vertices) is important.
+---------------------------------------------------------------------*/
+void CleanUp( void )
+{
+ CleanEdges();
+ CleanFaces();
+ CleanVertices();
+}
+
+/*---------------------------------------------------------------------
+CleanEdges runs through the edge list and cleans up the structure.
+If there is a newface then it will put that face in place of the
+visible face and NULL out newface. It also deletes so marked edges.
+---------------------------------------------------------------------*/
+void CleanEdges( void )
+{
+ tEdge e; /* Primary index into edge list. */
+ tEdge t; /* Temporary edge pointer. */
+
+ /* Integrate the newface's into the data structure. */
+ /* Check every edge. */
+ e = edges;
+ do {
+ if ( e->newface ) {
+ if ( e->adjface[0]->visible )
+ e->adjface[0] = e->newface;
+ else e->adjface[1] = e->newface;
+ e->newface = NULL;
+ }
+ e = e->next;
+ } while ( e != edges );
+
+ /* Delete any edges marked for deletion. */
+ while ( edges && edges->delete ) {
+ e = edges;
+ DELETE( edges, e );
+ }
+ e = edges->next;
+ do {
+ if ( e->delete ) {
+ t = e;
+ e = e->next;
+ DELETE( edges, t );
+ }
+ else e = e->next;
+ } while ( e != edges );
+}
+
+/*---------------------------------------------------------------------
+CleanFaces runs through the face list and deletes any face marked visible.
+---------------------------------------------------------------------*/
+void CleanFaces( void )
+{
+ tFace f; /* Primary pointer into face list. */
+ tFace t; /* Temporary pointer, for deleting. */
+
+
+ while ( faces && faces->visible ) {
+ f = faces;
+ DELETE( faces, f );
+ }
+ f = faces->next;
+ do {
+ if ( f->visible ) {
+ t = f;
+ f = f->next;
+ DELETE( faces, t );
+ }
+ else f = f->next;
+ } while ( f != faces );
+}
+
+/*---------------------------------------------------------------------
+CleanVertices runs through the vertex list and deletes the
+vertices that are marked as processed but are not incident to any
+undeleted edges.
+---------------------------------------------------------------------*/
+void CleanVertices( void )
+{
+ tEdge e;
+ tVertex v, t;
+
+ /* Mark all vertices incident to some undeleted edge as on the hull. */
+ e = edges;
+ do {
+ e->endpts[0]->onhull = e->endpts[1]->onhull = ONHULL;
+ e = e->next;
+ } while (e != edges);
+
+ /* Delete all vertices that have been processed but
+ are not on the hull. */
+ while ( vertices && vertices->mark && !vertices->onhull ) {
+ v = vertices;
+ DELETE( vertices, v );
+ }
+ v = vertices->next;
+ do {
+ if ( v->mark && !v->onhull ) {
+ t = v;
+ v = v->next;
+ DELETE( vertices, t )
+ }
+ else v = v->next;
+ } while ( v != vertices );
+
+ /* Reset flags. */
+ v = vertices;
+ do {
+ v->duplicate = NULL;
+ v->onhull = !ONHULL;
+ v = v->next;
+ } while ( v != vertices );
+}
+
+/*---------------------------------------------------------------------
+Collinear checks to see if the three points given are collinear,
+by checking to see if each element of the cross product is zero.
+---------------------------------------------------------------------*/
+bool Collinear( tVertex a, tVertex b, tVertex c )
+{
+ return
+ ( c->v[Z] - a->v[Z] ) * ( b->v[Y] - a->v[Y] ) -
+ ( b->v[Z] - a->v[Z] ) * ( c->v[Y] - a->v[Y] ) == 0
+ && ( b->v[Z] - a->v[Z] ) * ( c->v[X] - a->v[X] ) -
+ ( b->v[X] - a->v[X] ) * ( c->v[Z] - a->v[Z] ) == 0
+ && ( b->v[X] - a->v[X] ) * ( c->v[Y] - a->v[Y] ) -
+ ( b->v[Y] - a->v[Y] ) * ( c->v[X] - a->v[X] ) == 0 ;
+}
Property changes on: grass/trunk/vector/v.hull/chull.c
___________________________________________________________________
Name: svn:eol-style
+ native
Added: grass/trunk/vector/v.hull/chull.h
===================================================================
--- grass/trunk/vector/v.hull/chull.h (rev 0)
+++ grass/trunk/vector/v.hull/chull.h 2008-01-28 13:56:00 UTC (rev 29881)
@@ -0,0 +1,3 @@
+#include <grass/Vect.h>
+
+int make3DHull ( double *X, double *Y, double *Z, int num_points, struct Map_info *Map );
Property changes on: grass/trunk/vector/v.hull/chull.h
___________________________________________________________________
Name: svn:eol-style
+ native
Added: grass/trunk/vector/v.hull/globals.h
===================================================================
--- grass/trunk/vector/v.hull/globals.h (rev 0)
+++ grass/trunk/vector/v.hull/globals.h 2008-01-28 13:56:00 UTC (rev 29881)
@@ -0,0 +1,27 @@
+#define PROGVERSION 0.10
+#define PROGNAME "v.hull"
+
+/* if DEBUG > 1 we will dump even more details */
+#define DEBUG 0
+
+/* NULL valued cells */
+#define NULLVALUE -1
+/* masked cells */
+#define MASKVALUE -2
+/* unset cells */
+#define UNSET -3
+
+/* value to represent NULL in VTK files */
+#define DNULLVALUE -99999.99
+
+#define TMPFILE "voxeltmp.tmp"
+
+/* number of decimal places with which coordinates are stored */
+double PRECISION;
+
+/* verbose output includes progress display */
+int VERBOSE;
+
+/* number of DEMs in the input */
+int NSLICES;
+
Property changes on: grass/trunk/vector/v.hull/globals.h
___________________________________________________________________
Name: svn:eol-style
+ native
Added: grass/trunk/vector/v.hull/macros.h
===================================================================
--- grass/trunk/vector/v.hull/macros.h (rev 0)
+++ grass/trunk/vector/v.hull/macros.h 2008-01-28 13:56:00 UTC (rev 29881)
@@ -0,0 +1,39 @@
+/*====================================================================
+ macros.h
+
+ macros used to access data structures and perform quick tests.
+
+ ====================================================================*/
+
+/* general-purpose macros */
+#define SWAP(t,x,y) { t = x; x = y; y = t; }
+
+#define NEW(p,type) if ((p=(type *) malloc (sizeof(type))) == NULL) {\
+ printf ("Out of Memory!\n");\
+ exit(0);\
+ }
+
+#define FREE(p) if (p) { free ((char *) p); p = NULL; }
+
+
+#define ADD( head, p ) if ( head ) { \
+ p->next = head; \
+ p->prev = head->prev; \
+ head->prev = p; \
+ p->prev->next = p; \
+ } \
+ else { \
+ head = p; \
+ head->next = head->prev = p; \
+ }
+
+#define DELETE( head, p ) if ( head ) { \
+ if ( head == head->next ) \
+ head = NULL; \
+ else if ( p == head ) \
+ head = head->next; \
+ p->next->prev = p->prev; \
+ p->prev->next = p->next; \
+ FREE( p ); \
+ }
+
Property changes on: grass/trunk/vector/v.hull/macros.h
___________________________________________________________________
Name: svn:eol-style
+ native
More information about the grass-commit
mailing list