From 4713e82fbbe7ea5a7676dd324d81ac5fa884b169 Mon Sep 17 00:00:00 2001 From: Christophe Geuzaine <cgeuzaine@ulg.ac.be> Date: Thu, 10 Aug 2006 15:29:26 +0000 Subject: [PATCH] *** empty log message *** --- Fltk/Callbacks.cpp | 4 +- Graphics/CreateFile.cpp | 27 +- Graphics/CreateFile.h | 1 + Graphics/Makefile | 6 +- Graphics/Mesh.cpp | 148 +++- Graphics/tc.cpp | 1470 ++++++++++++++++++++++++++++++++++++++ Graphics/tc.h | 77 ++ Mesh/DiscreteSurface.cpp | 6 +- Mesh/Mesh.h | 1 - doc/CREDITS | 5 +- 10 files changed, 1724 insertions(+), 21 deletions(-) create mode 100644 Graphics/tc.cpp create mode 100644 Graphics/tc.h diff --git a/Fltk/Callbacks.cpp b/Fltk/Callbacks.cpp index e23de7051f..8a4d693c1c 100644 --- a/Fltk/Callbacks.cpp +++ b/Fltk/Callbacks.cpp @@ -1,4 +1,4 @@ -// $Id: Callbacks.cpp,v 1.426 2006-08-08 04:35:22 geuzaine Exp $ +// $Id: Callbacks.cpp,v 1.427 2006-08-10 15:29:25 geuzaine Exp $ // // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle // @@ -2825,7 +2825,7 @@ void mesh_save_cb(CALLBACK_ARGS) if(CTX.output_filename) strcpy(name, CTX.output_filename); else - GetDefaultMeshFileName(CTX.mesh.format, name); + GetDefaultFileName(CTX.mesh.format, name); if(CTX.confirm_overwrite) { if(!StatFile(name)) if(!fl_choice("File '%s' already exists.\n\nDo you want to replace it?", diff --git a/Graphics/CreateFile.cpp b/Graphics/CreateFile.cpp index 3a3e619d4d..73325fc21f 100644 --- a/Graphics/CreateFile.cpp +++ b/Graphics/CreateFile.cpp @@ -1,4 +1,4 @@ -// $Id: CreateFile.cpp,v 1.90 2006-08-07 22:02:29 geuzaine Exp $ +// $Id: CreateFile.cpp,v 1.91 2006-08-10 15:29:25 geuzaine Exp $ // // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle // @@ -51,13 +51,15 @@ int GuessFileFormatFromFileName(char *name) if(len <= 0) strcpy(ext, ""); - if(!strcmp(ext, ".geo")) return FORMAT_GEO; - else if(!strcmp(ext, ".opt")) return FORMAT_OPT; + if (!strcmp(ext, ".geo")) return FORMAT_GEO; else if(!strcmp(ext, ".msh")) return FORMAT_MSH; + else if(!strcmp(ext, ".pos")) return FORMAT_POS; + else if(!strcmp(ext, ".opt")) return FORMAT_OPT; else if(!strcmp(ext, ".unv")) return FORMAT_UNV; else if(!strcmp(ext, ".stl")) return FORMAT_STL; else if(!strcmp(ext, ".mesh")) return FORMAT_MESH; - else if(!strcmp(ext, ".pos")) return FORMAT_POS; + else if(!strcmp(ext, ".wrl")) return FORMAT_VRML; + else if(!strcmp(ext, ".vrml")) return FORMAT_VRML; else if(!strcmp(ext, ".gif")) return FORMAT_GIF; else if(!strcmp(ext, ".jpg")) return FORMAT_JPEG; else if(!strcmp(ext, ".jpeg")) return FORMAT_JPEG; @@ -72,8 +74,6 @@ int GuessFileFormatFromFileName(char *name) else if(!strcmp(ext, ".svg")) return FORMAT_SVG; else if(!strcmp(ext, ".ppm")) return FORMAT_PPM; else if(!strcmp(ext, ".yuv")) return FORMAT_YUV; - else if(!strcmp(ext, ".wrl")) return FORMAT_VRML; - else if(!strcmp(ext, ".vrml")) return FORMAT_VRML; else return -1; } @@ -82,11 +82,24 @@ void GetDefaultFileName(int format, char *name) char ext[10] = ""; strcpy(name, CTX.base_filename); switch(format){ + case FORMAT_GEO: strcpy(ext, ".geo"); break; case FORMAT_MSH: strcpy(ext, ".msh"); break; - case FORMAT_VRML: strcpy(ext, ".wrl"); break; + case FORMAT_POS: strcpy(ext, ".pos"); break; + case FORMAT_OPT: strcpy(ext, ".opt"); break; case FORMAT_UNV: strcpy(ext, ".unv"); break; case FORMAT_STL: strcpy(ext, ".stl"); break; case FORMAT_MESH: strcpy(ext, ".mesh"); break; + case FORMAT_VRML: strcpy(ext, ".wrl"); break; + case FORMAT_GIF: strcpy(ext, ".gif"); break; + case FORMAT_JPEG: strcpy(ext, ".jpg"); break; + case FORMAT_PNG: strcpy(ext, ".png"); break; + case FORMAT_PS: strcpy(ext, ".ps"); break; + case FORMAT_EPS: strcpy(ext, ".eps"); break; + case FORMAT_PDF: strcpy(ext, ".pdf"); break; + case FORMAT_TEX: strcpy(ext, ".tex"); break; + case FORMAT_SVG: strcpy(ext, ".svg"); break; + case FORMAT_PPM: strcpy(ext, ".ppm"); break; + case FORMAT_YUV: strcpy(ext, ".yuv"); break; default: break; } strcat(name, ext); diff --git a/Graphics/CreateFile.h b/Graphics/CreateFile.h index 0c6917b792..d052e53108 100644 --- a/Graphics/CreateFile.h +++ b/Graphics/CreateFile.h @@ -21,6 +21,7 @@ // Please report all bugs and problems to <gmsh@geuz.org>. int GuessFileFormatFromFileName(char *name); +void GetDefaultFileName(int format, char *name); void CreateOutputFile (char *name, int format); #endif diff --git a/Graphics/Makefile b/Graphics/Makefile index c726d89661..bbcf697de7 100644 --- a/Graphics/Makefile +++ b/Graphics/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.89 2006-08-07 22:02:30 geuzaine Exp $ +# $Id: Makefile,v 1.90 2006-08-10 15:29:25 geuzaine Exp $ # # Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle # @@ -43,8 +43,8 @@ SRC = Draw.cpp \ gl2jpeg.cpp\ gl2png.cpp\ gl2ppm.cpp\ - gl2yuv.cpp - + gl2yuv.cpp\ + tc.cpp OBJ = ${SRC:.cpp=.o} diff --git a/Graphics/Mesh.cpp b/Graphics/Mesh.cpp index 1708eb12bc..a81321bfa8 100644 --- a/Graphics/Mesh.cpp +++ b/Graphics/Mesh.cpp @@ -1,4 +1,4 @@ -// $Id: Mesh.cpp,v 1.156 2006-08-07 22:02:30 geuzaine Exp $ +// $Id: Mesh.cpp,v 1.157 2006-08-10 15:29:26 geuzaine Exp $ // // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle // @@ -25,11 +25,45 @@ #include "Draw.h" #include "Context.h" #include "VertexArray.h" +#include "OS.h" #include "gl2ps.h" extern GModel *GMODEL; extern Context_T CTX; +#include "tc.h" + +void renumberFaceVertices(GFace *f, List_T *xyz) +{ + std::list<GEdge*> ee = f->edges(); + std::list<GVertex*> vv = f->vertices(); + + int num = 0; + + for(std::list<GVertex*>::const_iterator it = vv.begin(); it != vv.end(); ++it){ + for(unsigned int i = 0; i < (*it)->mesh_vertices.size(); i++){ + MVertex *v = (*it)->mesh_vertices[i]; v->setNum(num++); + float x = v->x(), y = v->y(), z = v->z(); + List_Add(xyz, &x); List_Add(xyz, &y); List_Add(xyz, &z); + } + } + for(std::list<GEdge*>::const_iterator it = ee.begin(); it != ee.end(); ++it){ + for(unsigned int i = 0; i < (*it)->mesh_vertices.size(); i++){ + MVertex *v = (*it)->mesh_vertices[i]; v->setNum(num++); + float x = v->x(), y = v->y(), z = v->z(); + List_Add(xyz, &x); List_Add(xyz, &y); List_Add(xyz, &z); + } + } + for(unsigned int i = 0; i < f->mesh_vertices.size(); i++){ + MVertex *v = f->mesh_vertices[i]; v->setNum(num++); + float x = v->x(), y = v->y(), z = v->z(); + List_Add(xyz, &x); List_Add(xyz, &y); List_Add(xyz, &z); + } +} + +// define this to draw the vertex array by indexing elements +//#define ELEM + class drawMeshGFace { public : @@ -43,6 +77,116 @@ public : glPushName(s->tag()); } +#if 0 + static int first = 1; + static List_T *xyz; + static std::vector<List_T*> idx, idx2; + + if(first){ + first = 0; + printf("stripe surface %d\n", s->tag()); + xyz = List_Create(s->mesh_vertices.size(), 1000, sizeof(float)); + renumberFaceVertices(s, xyz); + + /* + for(int i = 0; i < List_Nbr(xyz)/3; i+=3){ + float x, y, z; + List_Read(xyz, i, &x); + List_Read(xyz, i+1, &y); + List_Read(xyz, i+2, &z); + printf("xyz = %f %f %f\n", x, y, z); + } + */ + ACTCData *tc = actcNew(); + actcParami(tc, ACTC_OUT_MIN_FAN_VERTS, INT_MAX); // generate only strips + //actcParami(tc, ACTC_OUT_MAX_PRIM_VERTS, INT_MAX); // optimum 12? + actcParami(tc, ACTC_OUT_MAX_PRIM_VERTS, 100); // optimum 12? + actcBeginInput(tc); + for(unsigned int i = 0; i < s->triangles.size(); i++){ + actcAddTriangle(tc, + s->triangles[i]->getVertex(0)->getNum(), + s->triangles[i]->getVertex(1)->getNum(), + s->triangles[i]->getVertex(2)->getNum()); + } + actcEndInput(tc); + actcBeginOutput(tc); + int strip, prim; + unsigned int v1, v2, v3; + strip = 0; + while((prim = actcStartNextPrim(tc, &v1, &v2)) != ACTC_DATABASE_EMPTY) { + strip++; +#ifdef ELEM + idx.push_back(List_Create(100, 100, sizeof(unsigned int))); + List_Add(idx[strip - 1], &v1); + List_Add(idx[strip - 1], &v2); +#else + idx2.push_back(List_Create(100, 100, sizeof(float))); + List_Add(idx2[strip - 1], List_Pointer_Fast(xyz, 3*v1)); + List_Add(idx2[strip - 1], List_Pointer_Fast(xyz, 3*v1+1)); + List_Add(idx2[strip - 1], List_Pointer_Fast(xyz, 3*v1+2)); + List_Add(idx2[strip - 1], List_Pointer_Fast(xyz, 3*v2)); + List_Add(idx2[strip - 1], List_Pointer_Fast(xyz, 3*v2+1)); + List_Add(idx2[strip - 1], List_Pointer_Fast(xyz, 3*v2+2)); +#endif + while(actcGetNextVert(tc, &v3) != ACTC_PRIM_COMPLETE){ +#ifdef ELEM + List_Add(idx[strip - 1], &v3); +#else + List_Add(idx2[strip - 1], List_Pointer_Fast(xyz, 3*v3)); + List_Add(idx2[strip - 1], List_Pointer_Fast(xyz, 3*v3+1)); + List_Add(idx2[strip - 1], List_Pointer_Fast(xyz, 3*v3+2)); +#endif + } + } + actcEndOutput(tc); + actcDelete(tc); + printf("stripe end\n"); + + } + + glEnableClientState(GL_VERTEX_ARRAY); +#ifdef ELEM + glVertexPointer(3, GL_FLOAT, 0, xyz->array); + for(unsigned int i = 0; i < idx.size(); i++){ + //printf("strip %d\n", i); + int n = List_Nbr(idx[i]); + glColor4ubv((GLubyte *)&CTX.color.mesh.carousel[i % 20]); + glDrawElements(GL_TRIANGLE_STRIP, n, GL_UNSIGNED_INT, idx[i]->array); + } +#else + for(unsigned int i = 0; i < idx2.size(); i++){ + //printf("strip %d\n", i); + int n = List_Nbr(idx2[i]); + glVertexPointer(3, GL_FLOAT, 0, idx2[i]->array); + glColor4ubv((GLubyte *)&CTX.color.mesh.carousel[i % 20]); + glDrawArrays(GL_TRIANGLE_STRIP, 0, n / 3); + } +#endif + glDisableClientState(GL_VERTEX_ARRAY); + + +#endif + + unsigned int col; + if(s->drawAttributes.Frozen > 0){ + col = CTX.color.geom.surface_sel; + } + else if(CTX.mesh.color_carousel == 1){ + col = CTX.color.mesh.carousel[abs(s->tag() % 20)]; + } + else if(CTX.mesh.color_carousel == 2){ + int n = 1; + int np = s->physicals.size(); + if(np) n = s->physicals[np - 1]; + col = CTX.color.mesh.carousel[abs(n % 20)]; + } + else if(CTX.mesh.color_carousel == 3){ + // partition + } + else + col = CTX.color.mesh.triangle; + glColor4ubv((GLubyte *)&col); + glBegin(GL_TRIANGLES); for(unsigned int i = 0; i < s->triangles.size(); i++){ MTriangle *t = s->triangles[i]; @@ -87,7 +231,7 @@ void Draw_Mesh() GMODEL->normals = new smooth_normals(CTX.mesh.angle_smooth_normals); } */ - + if(CTX.mesh.surfaces_faces || CTX.mesh.surfaces_edges) std::for_each(GMODEL->firstFace(), GMODEL->lastFace(), drawMeshGFace()); diff --git a/Graphics/tc.cpp b/Graphics/tc.cpp new file mode 100644 index 0000000000..06e7ff6869 --- /dev/null +++ b/Graphics/tc.cpp @@ -0,0 +1,1470 @@ +/* + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. All advertising materials mentioning features or use of this software + must display the following acknowledgement: + This product includes software developed by Brad Grantham and + Applied Conjecture. + 4. Neither the name Brad Grantham nor Applied Conjecture + may be used to endorse or promote products derived from this software + without specific prior written permission. + 5. Notification must be made to Brad Grantham about inclusion of this + software in a product including the author of the product and the name + and purpose of the product. Notification can be made using email + to Brad Grantham's current address (grantham@plunk.org as of September + 20th, 2000) or current U.S. mail address. + + * $Header: /cvsroot/gmsh/Graphics/tc.cpp,v 1.1 2006-08-10 15:29:26 geuzaine Exp $ + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <limits.h> +#include "tc.h" + +/* SNIPPET "table.c" Inducted Wed Nov 22 09:36:55 2000 */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#if !defined(MEM_CHART) +#define chartedSetLabel(a) +#endif + +#define LEVEL1COUNT 16384 +#define LEVEL2COUNT 1024 +#define LEVEL3COUNT 256 + +typedef struct TableLevel3 +{ + int EntryCount; + void *Table[LEVEL3COUNT]; + char IsSet[LEVEL3COUNT]; +} TableLevel3; + +typedef struct TableLevel2 +{ + int EntryCount; + TableLevel3 *Table[LEVEL2COUNT]; +} TableLevel2; + +typedef struct TableRoot +{ + size_t EntryCount; + size_t TotalEntryCount; + size_t TotalAllocatedBytes; + int EmptyEntryCount; + TableLevel2 *Table[LEVEL1COUNT]; +} TableRoot; + +typedef struct TableIterator { + int i1, i2, i3; + uint i; + TableLevel3 *CurLevel3; + int CheckLevel1, CheckLevel2; +} TableIterator; + +TableRoot *tableNew(void) +{ + TableRoot *tr; + + chartedSetLabel("table root"); + tr = (TableRoot *)calloc(sizeof(TableRoot), 1); + return tr; +} + +TableIterator *tableNewIterator(void) +{ + TableIterator *ti; + + chartedSetLabel("table iterator"); + ti = (TableIterator *)malloc(sizeof(TableIterator)); + return ti; +} + +int tableRetrieve(uint a, TableRoot *table, void **ref) +{ + int i1 = a / (LEVEL2COUNT * LEVEL3COUNT); + int i2 = (a / LEVEL3COUNT) % LEVEL2COUNT; + int i3 = a % LEVEL3COUNT; + + if(table->Table[i1] == NULL) + return 0; + if(table->Table[i1]->Table[i2] == NULL) + return 0; + if(!table->Table[i1]->Table[i2]->IsSet[i3]) + return 0; + if(ref != NULL) + *ref = table->Table[i1]->Table[i2]->Table[i3]; + return 1; +} + +int tableInsert(uint a, TableRoot *table, void *ref) +{ + int i1 = a / (LEVEL2COUNT * LEVEL3COUNT); + int i2 = (a / LEVEL3COUNT) % LEVEL2COUNT; + int i3 = a % LEVEL3COUNT; + + if(table->Table[i1] == NULL) { + chartedSetLabel("table level 2"); + table->Table[i1] = (TableLevel2 *)calloc(1, sizeof(TableLevel2)); + table->TotalAllocatedBytes += sizeof(TableLevel2); + if(table->Table[i1] == NULL) + return 0; + } + if(table->Table[i1]->Table[i2] == NULL) { + chartedSetLabel("table level 3"); + table->Table[i1]->Table[i2] = + (TableLevel3 *)calloc(1, sizeof(TableLevel3)); + table->TotalAllocatedBytes += sizeof(TableLevel3); + if(table->Table[i1]->Table[i2] == NULL) + return 0; + table->Table[i1]->EntryCount++; + table->TotalEntryCount += LEVEL3COUNT; + table->EmptyEntryCount += LEVEL3COUNT; + } + if(!table->Table[i1]->Table[i2]->IsSet[i3]) { + table->Table[i1]->Table[i2]->EntryCount++; + table->EmptyEntryCount --; + table->Table[i1]->Table[i2]->IsSet[i3] = 1; + } + table->Table[i1]->Table[i2]->Table[i3] = ref; + return 1; +} + +int tableRemove(uint a, TableRoot *table, void **wasref) +{ + int i1 = a / (LEVEL2COUNT * LEVEL3COUNT); + int i2 = (a / LEVEL3COUNT) % LEVEL2COUNT; + int i3 = a % LEVEL3COUNT; + + if(table->Table[i1] == NULL) + return 0; + if(table->Table[i1]->Table[i2] == NULL) + return 0; + if(!table->Table[i1]->Table[i2]->IsSet[i3]) + return 0; + if(wasref != NULL) + *wasref = table->Table[i1]->Table[i2]->Table[i3]; + table->Table[i1]->Table[i2]->IsSet[i3] = 0; + table->EmptyEntryCount ++; + if(--table->Table[i1]->Table[i2]->EntryCount == 0) { + table->EmptyEntryCount -= LEVEL3COUNT; + table->TotalEntryCount -= LEVEL3COUNT; + free(table->Table[i1]->Table[i2]); + table->TotalAllocatedBytes -= sizeof(TableLevel3); + table->Table[i1]->Table[i2] = NULL; + if(--table->Table[i1]->EntryCount == 0) { + table->TotalAllocatedBytes -= sizeof(TableLevel2); + free(table->Table[i1]); + table->Table[i1] = NULL; + } + } + return 1; +} + +void tableResetIterator(TableIterator *ti) +{ + ti->i1 = 0; + ti->i2 = 0; + ti->i3 = 0; + ti->i = 0; + ti->CheckLevel1 = 1; + ti->CheckLevel2 = 1; +} + +int tableIterate(TableRoot *table, TableIterator *ti, uint *i, void **ref) +{ + int done; + + done = 0; + while(ti->i1 < LEVEL1COUNT) { + if(ti->CheckLevel1 && table->Table[ti->i1] == NULL) { + ti->i += LEVEL2COUNT * LEVEL3COUNT; + ti->i1++; + continue; + } else + ti->CheckLevel1 = 0; + if(ti->CheckLevel2 && table->Table[ti->i1]->Table[ti->i2] == NULL) { + ti->i += LEVEL3COUNT; + if(++ti->i2 >= LEVEL2COUNT) { + ti->i2 = 0; + ti->i1++; + ti->CheckLevel1 = 1; + } + continue; + } else + ti->CheckLevel2 = 0; + if(ti->i3 == 0) + ti->CurLevel3 = table->Table[ti->i1]->Table[ti->i2]; + if(ti->CurLevel3->IsSet[ti->i3]) { + if(ref != NULL) + *ref = ti->CurLevel3->Table[ti->i3]; + if(i != NULL) + *i = ti->i; + done = 1; + } + ti->i++; + if(++ti->i3 >= LEVEL3COUNT) { + ti->i3 = 0; + ti->CheckLevel2 = 1; + if(++ti->i2 >= LEVEL2COUNT) { + ti->i2 = 0; + ti->i1++; + ti->CheckLevel1 = 1; + } + } + if(done) + return 1; + } + return 0; +} + +void tableDelete(TableRoot *table, void (*datumDelete)(void *datum)) +{ + int i1, i2, i3; + + for(i1 = 0; i1 < LEVEL1COUNT; i1++) { + if(table->Table[i1] != NULL) { + for(i2 = 0; i2 < LEVEL2COUNT; i2++) { + if(table->Table[i1]->Table[i2] != NULL) { + for(i3 = 0; i3 < LEVEL3COUNT; i3++) { + if(table->Table[i1]->Table[i2]->IsSet[i3]) + datumDelete(table->Table[i1]->Table[i2]->Table[i3]); + } + free(table->Table[i1]->Table[i2]); + } + } + free(table->Table[i1]); + table->Table[i1] = NULL; + } + } + table->TotalEntryCount = 0; + table->EmptyEntryCount = 0; + table->TotalAllocatedBytes = 0; +} + +void tableGetStats(TableRoot *table, size_t *totalBytes, size_t *emptyCount, + size_t *totalCount) +{ + if(emptyCount != NULL) + *emptyCount = table->EmptyEntryCount; + if(totalCount != NULL) + *totalCount = table->TotalEntryCount; + if(totalBytes != NULL) + *totalBytes = table->TotalAllocatedBytes; +} + +size_t tableGetIteratorSize(void) +{ + return sizeof(TableIterator); +} + +/* "table.c" ENDSNIPPET */ + +#if !defined(MEM_CHART) +#define chartedSetLabel(a) +#endif + +#if defined(DEBUG) +#define ACTC_DEBUG(a) a +#else +#define ACTC_DEBUG(a) +#endif + +#if defined(INFO) +#define ACTC_INFO(a) a +#else +#define ACTC_INFO(a) +#endif + + +#define ACTC_CHECK(a) \ + { \ + int theErrorNow; \ + theErrorNow = (a); \ + if(theErrorNow < 0) \ + return theErrorNow; \ + } + +typedef struct { + struct ACTCVertex *FinalVert; +} ACTCTriangle; + +typedef struct { + struct ACTCVertex *V2; + int Count; + int TriangleCount; + ACTCTriangle *Triangles; +} ACTCEdge; + +typedef struct ACTCVertex { + uint V; + int Count; + struct ACTCVertex **PointsToMe; + struct ACTCVertex *Next; + int EdgeCount; + ACTCEdge *Edges; +} ACTCVertex; + +/* private tokens */ +#define ACTC_NO_MATCHING_VERT -0x3000 +#define ACTC_FWD_ORDER 0 +#define ACTC_REV_ORDER 1 + +#define MAX_STATIC_VERTS 10000000 /* buh? */ + +struct _ACTCData { + + /* vertex and edge database */ + int VertexCount; + TableRoot *Vertices; + TableIterator *VertexIterator; + int CurMaxVertValence; + int CurMinVertValence; + ACTCVertex **VertexBins; + + /* alternate vertex array if range small enough */ + ACTCVertex *StaticVerts; + int UsingStaticVerts; + uint VertRange; + + /* During consolidation */ + int CurWindOrder; + int PrimType; + ACTCVertex *V1; + ACTCVertex *V2; + int VerticesSoFar; + + /* Error and state handling */ + int IsInputting; + int IsOutputting; + int Error; + + /* actcParam-settable parameters */ + uint MinInputVert; + uint MaxInputVert; + int MaxVertShare; + int MaxEdgeShare; + int MinFanVerts; + int MaxPrimVerts; + int HonorWinding; +}; + +#if defined(DEBUG) || defined(INFO) + +static void dumpTriangles(ACTCEdge *e, FILE *fp) +{ + int i; + int c; + char v[12]; + + c = fprintf(fp, " %d triangles: "); + for(i = 0; i < e->TriangleCount; i++) { + if(c + 1 + sprintf(v, "%u", e->Triangles[i].FinalVert) > 78) { + fputs("\n", fp); + c = fprintf(fp, " "); + } + c += fprintf(fp, " %s", v); + } + fputs("\n", fp); +} + +static void dumpEdges(ACTCVertex *vert, FILE *fp) +{ + int i; + int c; + char v[26]; /* two signed ints plus x plus NUL */ + + for(i = 0; i < vert->EdgeCount; i++) { + fprintf(fp, " %u->%u (%d times)\n", vert->V, vert->Edges[i].V2->V, + vert->Edges[i].Count); + dumpTriangles(&vert->Edges[i], fp); + } + fputs("\n", fp); +} + +static void dumpVertices(ACTCData *tc, FILE *fp) +{ + int i; + ACTCVertex *v; + + if(!tc->UsingStaticVerts) + tableResetIterator(tc->VertexIterator); + + fprintf(fp, "%d vertices in valences list\n", tc->VertexCount); + if(tc->UsingStaticVerts) { + for(i = 0; i < tc->VertRange; i++) { + v = &tc->StaticVerts[i]; + if(v->Count > 0) { + fprintf(fp, " vertex %u, valence %d, %d edges\n", v->V, + v->Count, v->EdgeCount); + dumpEdges(v, fp); + } + } + } else { + for(i = 0; i < tc->VertexCount; i++) { + if(tableIterate(tc->Vertices, tc->VertexIterator, NULL, + (void **)&v) == 0) { + fprintf(fp, "ACTC::dumpVertices : fewer vertices in the table " + "than we expected!\n"); + fprintf(stderr, "ACTC::dumpVertices : fewer vertices in the table " + "than we expected!\n"); + } + if(v == NULL) { + fprintf(fp, "ACTC::dumpVertices : did not expect to get a NULL" + "Vertex from the table iterator!\n"); + fprintf(stderr, "ACTC::dumpVertices : did not expect to get a NULL" + "Vertex from the table iterator!\n"); + } + fprintf(fp, " vertex %u, valence %d, %d edges\n", v->V, v->Count, + v->EdgeCount); + dumpEdges(v, fp); + } + } +} + +static void dumpVertexBins(ACTCData *tc, FILE *fp) +{ + ACTCVertex *cur; + int i; + int c; + char v[26]; /* two signed ints plus x plus NUL */ + + fprintf(fp, "vertex bins:\n"); + if(tc->VertexBins == NULL) { + fprintf(fp, " empty.\n"); + return; + } + for(i = 1; i <= tc->CurMaxVertValence; i++) { + cur = tc->VertexBins[i]; + c = fprintf(fp, " bin %d -> ", i); + while(cur != NULL) { + if(c + 1 + sprintf(v, "%ux%d", cur->V, cur->Count) > 78) { + fputs("\n", fp); + c = fprintf(fp, " "); + } + c += fprintf(fp, " %s", v); + cur = cur->Next; + } + fputs("\n", fp); + } +} + +void actcDumpState(ACTCData *tc, FILE *fp) +{ + dumpVertices(tc, fp); + dumpVertexBins(tc, fp); +} + +#endif /* DEBUG || INFO */ + +#if defined(DEBUG) + +static int abortWithOptionalDump(ACTCData *tc) +{ + ACTC_INFO(actcDumpState(tc, stderr)); + abort(); +} + +#endif /* defined(DEBUG) */ + +int actcGetError(ACTCData *tc) +{ + int error = tc->Error; + tc->Error = ACTC_NO_ERROR; + return error; +} + +static void *reallocAndAppend(void **ptr, uint *itemCount, size_t itemBytes, + void *append) +{ + void *t; + + t = realloc(*ptr, itemBytes * (*itemCount + 1)); + if(t == NULL) + return NULL; + *ptr = t; + + memcpy((unsigned char *)*ptr + *itemCount * itemBytes, append, itemBytes); + (*itemCount) += 1; + + return *ptr; +} + +/* + * Call only during input; changes vertices' valences and does not + * fix the bins that are ordered by vertex valence. (It's usually cheaper + * to traverse the vertex list once after all are added, since that's + * linear in the NUMBER OF UNIQUE VERTEX INDICES, which is almost always + * going to be less than the number of vertices.) + */ +static int incVertexValence(ACTCData *tc, uint v, ACTCVertex **found) +{ + ACTCVertex *vertex; + + if(tc->UsingStaticVerts) { + vertex = &tc->StaticVerts[v]; + vertex->Count++; + if(vertex->Count == 1) { + vertex->V = v; + tc->VertexCount++; + } + } else { + if(tableRetrieve(v, tc->Vertices, (void **)&vertex) == 1) { + if(vertex->V != v) { + ACTC_DEBUG( + fprintf(stderr, "ACTC::incVertexValence : Got vertex %d when " + "looking for vertex %d?!?\n", vertex->V, v); + abortWithOptionalDump(tc); + ) + return tc->Error = ACTC_DATABASE_CORRUPT; + } + vertex->Count++; + } else { + chartedSetLabel("new Vertex"); + vertex = (ACTCVertex *)malloc(sizeof(ACTCVertex)); + vertex->V = v; + vertex->Count = 1; + vertex->Edges = NULL; + vertex->EdgeCount = 0; + if(tableInsert(v, tc->Vertices, vertex) == 0) { + ACTC_DEBUG(fprintf(stderr, "ACTC::incVertexValence : Failed " + "to insert vertex into table\n");) + return tc->Error = ACTC_ALLOC_FAILED; + } + tc->VertexCount++; + } + } + if(vertex->Count > tc->CurMaxVertValence) + tc->CurMaxVertValence = vertex->Count; + + *found = vertex; + + return ACTC_NO_ERROR; +} + +static int decVertexValence(ACTCData *tc, ACTCVertex **vptr) +{ + ACTCVertex *v = *vptr; + + v->Count--; + if(v->Count < 0) { + ACTC_DEBUG( + fprintf(stderr, "ACTC::decVertexValence : Valence went " + "negative?!?\n"); + abortWithOptionalDump(tc); + ) + return tc->Error = ACTC_DATABASE_CORRUPT; + } + + if(v->PointsToMe != NULL) { + *v->PointsToMe = v->Next; + if(v->Next != NULL) + v->Next->PointsToMe = v->PointsToMe; + v->Next = NULL; + } + + if(v->Count == 0) { + tc->VertexCount--; + if(v->Edges != NULL) + free(v->Edges); + if(!tc->UsingStaticVerts) { + tableRemove(v->V, tc->Vertices, NULL); + free(v); + } + *vptr = NULL; + } else { + if(tc->VertexBins != NULL) { + v->Next = tc->VertexBins[v->Count]; + v->PointsToMe = &tc->VertexBins[v->Count]; + if(v->Next != NULL) + v->Next->PointsToMe = &v->Next; + tc->VertexBins[v->Count] = v; + if(v->Count < tc->CurMinVertValence) + tc->CurMinVertValence = v->Count; + } + } + + return ACTC_NO_ERROR; +} + +static int findNextFanVertex(ACTCData *tc, ACTCVertex **vert) +{ + if(tc->CurMaxVertValence < tc->MinFanVerts) { + return ACTC_NO_MATCHING_VERT; + } + while(tc->VertexBins[tc->CurMaxVertValence] == NULL) { + tc->CurMaxVertValence--; + if(tc->CurMaxVertValence < tc->CurMinVertValence) { + if(tc->VertexCount > 0) { + ACTC_DEBUG(fprintf(stderr, "tc::findNextFanVertex : no more " + "vertices in bins but VertexCount > 0\n");) + return tc->Error = ACTC_DATABASE_CORRUPT; + } + return ACTC_NO_MATCHING_VERT; + } + } + *vert = tc->VertexBins[tc->CurMaxVertValence]; + return ACTC_NO_ERROR; +} + +static int findNextStripVertex(ACTCData *tc, ACTCVertex **vert) +{ + while(tc->VertexBins[tc->CurMinVertValence] == NULL) { + tc->CurMinVertValence++; + if(tc->CurMinVertValence > tc->CurMaxVertValence) { + if(tc->VertexCount > 0) { + ACTC_DEBUG(fprintf(stderr, "tc::findNextStripVertex : no more " + "vertices in bins but VertexCount > 0\n");) + return tc->Error = ACTC_DATABASE_CORRUPT; + } + return ACTC_NO_MATCHING_VERT; + } + } + *vert = tc->VertexBins[tc->CurMinVertValence]; + return ACTC_NO_ERROR; +} + +int actcGetIsDuringInput(ACTCData *tc) { + return tc->IsInputting; +} + +int actcBeginInput(ACTCData *tc) +{ + if(tc->IsOutputting) { + ACTC_DEBUG(fprintf(stderr, "actcBeginInput : called within " + "BeginOutput/EndOutput\n");) + return tc->Error = ACTC_DURING_INPUT; + } + + if(tc->IsInputting) { + ACTC_DEBUG(fprintf(stderr, "actcBeginInput : called within " + "BeginInput/EndInput\n");) + return tc->Error = ACTC_DURING_INPUT; + } + + tc->IsInputting = 1; + tc->CurMaxVertValence = 0; + + if(tc->MaxInputVert < MAX_STATIC_VERTS - 1) { + size_t byteCount; + tc->UsingStaticVerts = 1; + tc->VertRange = tc->MaxInputVert + 1; + byteCount = sizeof(ACTCVertex) * tc->VertRange; + chartedSetLabel("static verts"); + tc->StaticVerts = (ACTCVertex *)calloc(sizeof(ACTCVertex), tc->VertRange); + if(tc->StaticVerts == NULL) { + ACTC_INFO(printf("Couldn't allocate static %d vert block of %u " + "bytes\n", tc->VertRange, byteCount);) + tc->UsingStaticVerts = 0; + } + } else + tc->UsingStaticVerts = 0; + + return ACTC_NO_ERROR; +} + +int actcEndInput(ACTCData *tc) +{ + if(tc->IsOutputting) { + ACTC_DEBUG(fprintf(stderr, "actcEndInput : called within " + "BeginOutput/EndOutput\n");) + return tc->Error = ACTC_DURING_OUTPUT; + } + + if(!tc->IsInputting) { + ACTC_DEBUG(fprintf(stderr, "actcEndInput : called outside " + "BeginInput/EndInput\n");) + return tc->Error = ACTC_IDLE; + } + + tc->IsInputting = 0; + + return ACTC_NO_ERROR; +} + +int actcGetIsDuringOutput(ACTCData *tc) { + return tc->IsOutputting; +} + +int actcBeginOutput(ACTCData *tc) +{ + ACTCVertex *v; + int i; + + if(tc->IsInputting) { + ACTC_DEBUG(fprintf(stderr, "actcBeginOutput : called within " + "BeginInput/EndInput\n");) + return tc->Error = ACTC_DURING_INPUT; + } + + if(tc->IsOutputting) { + ACTC_DEBUG(fprintf(stderr, "actcBeginOutput : called within " + "BeginOutput/EndOutput\n");) + return tc->Error = ACTC_DURING_OUTPUT; + } + + tc->IsOutputting = 1; + + tc->CurMinVertValence = INT_MAX; + chartedSetLabel("vertex bins"); + tc->VertexBins = (ACTCVertex **)calloc(sizeof(ACTCVertex *), tc->CurMaxVertValence + 1); + if(tc->VertexBins == NULL) { + ACTC_DEBUG(fprintf(stderr, "actcBeginOutput : couldn't allocate %d bytes " + "for Vertex Bins\n", + sizeof(ACTCVertex *) * tc->CurMaxVertValence);) + return tc->Error = ACTC_ALLOC_FAILED; + } + + if(tc->UsingStaticVerts) { + double edgeTotal; + for(i = 0; i < (int)tc->VertRange; i++) { //gmsh: cast + v = &tc->StaticVerts[i]; + if(v->Count > 0) { + v->Next = tc->VertexBins[v->Count]; + v->PointsToMe = &tc->VertexBins[v->Count]; + tc->VertexBins[v->Count] = v; + if(v->Next != NULL) + v->Next->PointsToMe = &v->Next; + if(v->Count < tc->CurMinVertValence) + tc->CurMinVertValence = v->Count; + edgeTotal += v->EdgeCount; + } + } + } else { + tableResetIterator(tc->VertexIterator); + for(i = 0; i < tc->VertexCount; i++) { + if(tableIterate(tc->Vertices, tc->VertexIterator, NULL, (void **)&v) + == 0) { + ACTC_DEBUG(fprintf(stderr, "actcBeginOutput : fewer vertices in " + "the table than we expected!\n");) + return tc->Error = ACTC_DATABASE_CORRUPT; + } + v->Next = tc->VertexBins[v->Count]; + v->PointsToMe = &tc->VertexBins[v->Count]; + tc->VertexBins[v->Count] = v; + if(v->Next != NULL) + v->Next->PointsToMe = &v->Next; + if(v->Count < tc->CurMinVertValence) + tc->CurMinVertValence = v->Count; + } + } + + return ACTC_NO_ERROR; +} + +int actcEndOutput(ACTCData *tc) +{ + if(tc->IsInputting) { + ACTC_DEBUG(fprintf(stderr, "actcEndOutput : called within " + "BeginInput/EndInput\n");) + return tc->Error = ACTC_DURING_INPUT; + } + + if(!tc->IsOutputting) { + ACTC_DEBUG(fprintf(stderr, "actcEndOutput : called outside " + "BeginOutput/EndOutput\n");) + return tc->Error = ACTC_IDLE; + } + + tc->IsOutputting = 0; + + if(tc->UsingStaticVerts) { + free(tc->StaticVerts); + tc->StaticVerts = NULL; + tc->UsingStaticVerts = 0; + } + + free(tc->VertexBins); + tc->VertexBins = NULL; + + return ACTC_NO_ERROR; +} + +ACTCData *actcNew(void) +{ + ACTCData *tc; +#if defined(DEBUG) || defined(INFO) + static int didPrintVersion = 0; + + if(!didPrintVersion) { + int verMinor, verMajor; + didPrintVersion = 1; + + actcGetParami(tc, ACTC_MAJOR_VERSION, &verMajor); + actcGetParami(tc, ACTC_MINOR_VERSION, &verMinor); + fprintf(stderr, "TC Version %d.%d\n", verMajor, verMinor); + } +#endif /* defined(DEBUG) || defined(INFO) */ + + chartedSetLabel("the tc struct"); + tc = (ACTCData *)calloc(sizeof(*tc), 1); + + if(tc == NULL) { + ACTC_DEBUG(fprintf(stderr, "actcNew : couldn't allocate %d bytes " + "for new ACTCData\n", sizeof(*tc));) + return NULL; + } + + tc->Vertices = tableNew(); + tc->VertexIterator = tableNewIterator(); + + tc->MinFanVerts = INT_MAX; + tc->MaxPrimVerts = INT_MAX; + tc->MaxInputVert = INT_MAX; + tc->MaxEdgeShare = INT_MAX; + tc->MaxVertShare = INT_MAX; + tc->HonorWinding = 1; + /* seed = 0 handled by calloc */ + /* XXX grantham 20000615 - seed ignored for now */ + + return tc; +} + +static size_t allocatedForTriangles(ACTCEdge *e) +{ + return sizeof(ACTCTriangle) * e->TriangleCount; +} + +static size_t allocatedForEdges(ACTCVertex *vert) +{ + int i; + size_t size; + + size = sizeof(ACTCEdge) * vert->EdgeCount; + for(i = 0; i < vert->EdgeCount; i++) { + size += allocatedForTriangles(&vert->Edges[i]); + } + return size; +} + +static size_t allocatedForVertices(ACTCData *tc) +{ + int i; + int size=0;//gmsh: init + ACTCVertex *v; + + if(!tc->UsingStaticVerts) + tableResetIterator(tc->VertexIterator); + + if(tc->UsingStaticVerts) { + size = tc->VertRange * sizeof(ACTCVertex); + for(i = 0; i < (int)tc->VertRange; i++) { //gmsh: cast + v = &tc->StaticVerts[i]; + if(v->Count > 0) + size += allocatedForEdges(v); + } + } else { + for(i = 0; i < tc->VertexCount; i++) { + tableIterate(tc->Vertices, tc->VertexIterator, NULL, (void **)&v); + size += allocatedForEdges(v); + } + } + return size; +} + +int actcGetMemoryAllocation(ACTCData *tc, size_t *bytesAllocated) +{ + size_t tableBytes; + + tableGetStats(tc->Vertices, NULL, NULL, &tableBytes); + *bytesAllocated = sizeof(ACTCData); + *bytesAllocated += tableBytes; + *bytesAllocated += allocatedForVertices(tc); /* recurses */ + + return ACTC_NO_ERROR; +} + +static void freeVertex(void *p) +{ + ACTCVertex *v = (ACTCVertex *)p; + int i; + + for(i = 0; i < v->EdgeCount; i++) + free(v->Edges[i].Triangles); + free(v->Edges); + free(v); +} + +int actcMakeEmpty(ACTCData *tc) +{ + tc->VertexCount = 0; + if(!tc->UsingStaticVerts) + tableDelete(tc->Vertices, freeVertex); + if(tc->VertexBins != NULL) { + free(tc->VertexBins); + tc->VertexBins = NULL; + } + tc->IsOutputting = 0; + tc->IsInputting = 0; + return ACTC_NO_ERROR; +} + +void actcDelete(ACTCData *tc) +{ + actcMakeEmpty(tc); + free(tc->VertexIterator); + free(tc->Vertices); + free(tc); +} + +int actcParami(ACTCData *tc, int param, int value) +{ + if(tc->IsInputting) { + ACTC_DEBUG(fprintf(stderr, "actcParami : within BeginInput/" + "EndInput\n");) + return tc->Error = ACTC_DURING_INPUT; + } + if(tc->IsOutputting) { + ACTC_DEBUG(fprintf(stderr, "actcParami : within BeginOutput/" + "EndOutput\n");) + return tc->Error = ACTC_DURING_OUTPUT; + } + switch(param) { + case ACTC_OUT_MIN_FAN_VERTS: + tc->MinFanVerts = value; + break; + + case ACTC_IN_MAX_VERT: + if(value < (int)tc->MinInputVert) { // gmsh: cast + ACTC_DEBUG(fprintf(stderr, "actcParami : tried to set " + "MAX_INPUT_VERT to %d, less than MIN_INPUT_VERT (%d)\n", + value, tc->MinInputVert);) + return tc->Error = ACTC_INVALID_VALUE; + } + tc->MaxInputVert = value; + break; + + case ACTC_IN_MIN_VERT: + if(value > (int)tc->MaxInputVert) { // gmsh:cast + ACTC_DEBUG(fprintf(stderr, "actcParami : tried to set " + "MIN_INPUT_VERT to %d, greater than MAX_INPUT_VERT (%d)\n", + value, tc->MaxInputVert);) + return tc->Error = ACTC_INVALID_VALUE; + } + tc->MinInputVert = value; + break; + + case ACTC_IN_MAX_EDGE_SHARING: + tc->MaxEdgeShare = value; + break; + + case ACTC_IN_MAX_VERT_SHARING: + tc->MaxVertShare = value; + break; + + case ACTC_OUT_HONOR_WINDING: + tc->HonorWinding = value; + break; + + case ACTC_OUT_MAX_PRIM_VERTS: + if(value < 3) { + ACTC_DEBUG(fprintf(stderr, "actcParami : tried to set " + "MAX_PRIM_VERTS to %d (needed to be 3 or more)\n", value);) + return tc->Error = ACTC_INVALID_VALUE; + } + tc->MaxPrimVerts = value; + break; + + } + return ACTC_NO_ERROR; +} + +int actcParamu(ACTCData *tc, int param, uint value) +{ + /* + * XXX - yes, this is questionable, but I consulted industry + * experts and we agreed that most common behavior is to copy the + * bits directly, which is what I want. + */ + return actcParami(tc, param, (int)value); +} + +int actcGetParami(ACTCData *tc, int param, int *value) +{ + switch(param) { + case ACTC_MAJOR_VERSION: + *value = 1; + break; + + case ACTC_MINOR_VERSION: + *value = 1; + break; + + case ACTC_IN_MAX_VERT: + *value = tc->MaxInputVert; + break; + + case ACTC_IN_MIN_VERT: + *value = tc->MinInputVert; + break; + + case ACTC_IN_MAX_EDGE_SHARING: + *value = tc->MaxEdgeShare; + break; + + case ACTC_IN_MAX_VERT_SHARING: + *value = tc->MaxVertShare; + break; + + case ACTC_OUT_MIN_FAN_VERTS: + *value = tc->MinFanVerts; + break; + + case ACTC_OUT_HONOR_WINDING: + *value = tc->HonorWinding; + break; + + case ACTC_OUT_MAX_PRIM_VERTS: + *value = tc->MaxPrimVerts; + break; + + default: + *value = 0; + return tc->Error = ACTC_INVALID_VALUE; + /* break; */ + } + return ACTC_NO_ERROR; +} + +int actcGetParamu(ACTCData *tc, int param, uint *value) +{ + return actcGetParami(tc, param, (int *)value); +} + +static int mapEdgeTriangle(ACTCData *tc, ACTCEdge *edge, ACTCVertex *v3) +{ + ACTCTriangle tmp; + void *r; + + tmp.FinalVert = v3; + chartedSetLabel("triangle list"); + r = reallocAndAppend((void **)&edge->Triangles, (uint*)&edge->TriangleCount,//gmsh: uint cast + sizeof(tmp), &tmp); + if(r == NULL) { + ACTC_DEBUG(fprintf(stderr, "ACTC::mapEdgeTriangle : Couldn't allocate " + "%d bytes for triangles\n", sizeof(tmp) * + (edge->TriangleCount + 1));) + return tc->Error = ACTC_ALLOC_FAILED; + } + + return ACTC_NO_ERROR; +} + +static int unmapEdgeTriangle(ACTCData *tc, ACTCEdge *edge, ACTCVertex *v3) +{ + int i; + + for(i = 0; i < edge->TriangleCount; i++) + if(edge->Triangles[i].FinalVert == v3) + break; + + if(i == edge->TriangleCount) { + ACTC_DEBUG( + fprintf(stderr, "ACTC::unmapEdgeTriangle : Couldn't find third vertex" + " from edge in order to delete it?!?\n"); + abortWithOptionalDump(tc); + ) + return tc->Error = ACTC_DATABASE_CORRUPT; + } + + edge->Triangles[i] = edge->Triangles[edge->TriangleCount - 1]; + edge->TriangleCount --; + + return ACTC_NO_ERROR; +} + +static int mapVertexEdge(ACTCData *tc, ACTCVertex *v1, ACTCVertex *v2, ACTCEdge **edge) +{ + uint i; + ACTCEdge tmp; + void *r; + + for(i = 0; i < (uint)v1->EdgeCount; i++)//gmsh: cast + if(v1->Edges[i].V2 == v2) { + v1->Edges[i].Count++; + break; + } + + if(i == (uint)v1->EdgeCount) {//gmsh: cast + + tmp.V2 = v2; + tmp.Count = 1; + tmp.Triangles = NULL; + tmp.TriangleCount = 0; + + chartedSetLabel("vert-to-edge mapping"); + r = reallocAndAppend((void **)&v1->Edges, (uint*)&v1->EdgeCount,//gmsh: uint cast + sizeof(tmp), &tmp); + if(r == NULL) { + ACTC_DEBUG(fprintf(stderr, "ACTC::mapVertexEdge : Couldn't reallocate " + "to %d bytes for vertex's edge list\n", sizeof(tmp) * + v1->EdgeCount);) + return tc->Error = ACTC_ALLOC_FAILED; + } + } + *edge = &v1->Edges[i]; + + return ACTC_NO_ERROR; +} + +static int unmapVertexEdge(ACTCData *tc, ACTCVertex *v1, ACTCVertex *v2) +{ + int i; + + for(i = 0; i < v1->EdgeCount; i++) + if(v1->Edges[i].V2 == v2) + break; + + if(i == v1->EdgeCount) { + ACTC_DEBUG( + fprintf(stderr, "ACTC::unmapVertexEdge : Couldn't find edge %d,%d" + " from vertex in order to unmap it?!?\n", v1->V, v2->V); + abortWithOptionalDump(tc); + ) + return tc->Error = ACTC_DATABASE_CORRUPT; + } + + v1->Edges[i].Count --; + if(v1->Edges[i].Count == 0) { + if(v1->Edges[i].Triangles != NULL) + free(v1->Edges[i].Triangles); + v1->Edges[i] = v1->Edges[v1->EdgeCount - 1]; + v1->EdgeCount --; + } + + return ACTC_NO_ERROR; +} + +int actcAddTriangle(ACTCData *tc, uint v1, uint v2, uint v3) +{ + ACTCVertex *vertexRec1; + ACTCVertex *vertexRec2; + ACTCVertex *vertexRec3; + + ACTCEdge *edge12; + ACTCEdge *edge23; + ACTCEdge *edge31; + + if(tc->IsOutputting) { + ACTC_DEBUG(fprintf(stderr, "actcAddTriangle : inside " + "BeginOutput/EndOutput\n");) + return tc->Error = ACTC_IDLE; + } + if(!tc->IsInputting) { + ACTC_DEBUG(fprintf(stderr, "actcAddTriangle : outside " + "BeginInput/EndInput\n");) + return tc->Error = ACTC_DURING_INPUT; + } + + if(incVertexValence(tc, v1, &vertexRec1) != ACTC_NO_ERROR) goto returnError1; + if(incVertexValence(tc, v2, &vertexRec2) != ACTC_NO_ERROR) goto free1; + if(incVertexValence(tc, v3, &vertexRec3) != ACTC_NO_ERROR) goto free2; + + if(mapVertexEdge(tc, vertexRec1, vertexRec2, &edge12) != ACTC_NO_ERROR) + goto free3; + if(mapVertexEdge(tc, vertexRec2, vertexRec3, &edge23) != ACTC_NO_ERROR) + goto free4; + if(mapVertexEdge(tc, vertexRec3, vertexRec1, &edge31) != ACTC_NO_ERROR) + goto free5; + + if(mapEdgeTriangle(tc, edge12, vertexRec3) != ACTC_NO_ERROR) goto free6; + if(mapEdgeTriangle(tc, edge23, vertexRec1) != ACTC_NO_ERROR) goto free7; + if(mapEdgeTriangle(tc, edge31, vertexRec2) != ACTC_NO_ERROR) goto free8; + + return ACTC_NO_ERROR; + + /* + * XXX Unfortunately, while backing out during the following + * statements, we might encounter errors in the database which + * will not get returned properly to the caller; I take heart in + * the fact that if such an error occurs, TC is just a moment from + * core dumping anyway. XXX grantham 20000615 + */ + +free8: + unmapEdgeTriangle(tc, edge23, vertexRec1); +free7: + unmapEdgeTriangle(tc, edge12, vertexRec3); +free6: + unmapVertexEdge(tc, vertexRec3, vertexRec1); +free5: + unmapVertexEdge(tc, vertexRec2, vertexRec3); +free4: + unmapVertexEdge(tc, vertexRec1, vertexRec2); +free3: + decVertexValence(tc, &vertexRec3); +free2: + decVertexValence(tc, &vertexRec2); +free1: + decVertexValence(tc, &vertexRec1); +returnError1: + return tc->Error; +} + +int actcStartNextPrim(ACTCData *tc, uint *v1Return, uint *v2Return) +{ + ACTCVertex *v1 = NULL; + ACTCVertex *v2 = NULL; + int findResult; + + if(tc->IsInputting) { + ACTC_DEBUG(fprintf(stderr, "actcStartNextPrim : within " + "BeginInput/EndInput\n");) + return tc->Error = ACTC_DURING_INPUT; + } + if(!tc->IsOutputting) { + ACTC_DEBUG(fprintf(stderr, "actcStartNextPrim : outside " + "BeginOutput/EndOutput\n");) + return tc->Error = ACTC_IDLE; + } + + findResult = findNextFanVertex(tc, &v1); + if(findResult == ACTC_NO_ERROR) + tc->PrimType = ACTC_PRIM_FAN; + else if(findResult != ACTC_NO_MATCHING_VERT) { + ACTC_DEBUG(fprintf(stderr, "actcStartNextPrim : internal " + "error finding next appropriate vertex\n");) + return tc->Error = findResult; + } else { + findResult = findNextStripVertex(tc, &v1); + if(findResult != ACTC_NO_ERROR && findResult != ACTC_NO_MATCHING_VERT) { + ACTC_DEBUG(fprintf(stderr, "actcStartNextPrim : internal " + "error finding next appropriate vertex\n");) + return tc->Error = findResult; + } + tc->PrimType = ACTC_PRIM_STRIP; + } + + if(findResult == ACTC_NO_MATCHING_VERT) { + *v1Return = (uint)-1; //gmsh: cast + *v2Return = (uint)-1; //gmsh: cast + return tc->Error = ACTC_DATABASE_EMPTY; + } + + v2 = v1->Edges[0].V2; + + tc->CurWindOrder = ACTC_FWD_ORDER; + tc->VerticesSoFar = 2; + + tc->V1 = v1; + tc->V2 = v2; + + *v1Return = v1->V; + *v2Return = v2->V; + + ACTC_INFO(printf("starting with edge %u, %u\n", tc->V1->V, tc->V2->V);) + + return tc->PrimType; +} + +static int findEdge(ACTCVertex *v1, ACTCVertex *v2, ACTCEdge **edge) +{ + int i; + + for(i = 0; i < v1->EdgeCount; i++) + if(v1->Edges[i].V2 == v2) { + *edge = &v1->Edges[i]; + return 1; + } + return 0; +} + +int unmapEdgeTriangleByVerts(ACTCData *tc, ACTCVertex *v1, ACTCVertex *v2, + ACTCVertex *v3) +{ + ACTCEdge *e; + + ACTC_CHECK(findEdge(v1, v2, &e)); + unmapEdgeTriangle(tc, e, v3); + return ACTC_NO_ERROR; +} + +int actcGetNextVert(ACTCData *tc, uint *vertReturn) +{ + ACTCEdge *edge; + int wasEdgeFound = 0; + ACTCVertex *thirdVertex; + int wasFoundReversed; + + if(tc->IsInputting) { + ACTC_DEBUG(fprintf(stderr, "actcGetNextVert : within BeginInput/" + "EndInput\n");) + return tc->Error = ACTC_DURING_INPUT; + } + if(!tc->IsOutputting) { + ACTC_DEBUG(fprintf(stderr, "actcGetNextVert : outside BeginOutput/" + "EndOutput\n");) + return tc->Error = ACTC_IDLE; + } + if(tc->PrimType == -1) { + ACTC_DEBUG(fprintf(stderr, "actcGetNextVert : Asked for next vertex " + "without a primitive (got last\n vertex already?)\n");) + return tc->Error = ACTC_INVALID_VALUE; + } + + if(tc->VerticesSoFar >= tc->MaxPrimVerts) { + tc->PrimType = -1; + return tc->Error = ACTC_PRIM_COMPLETE; + } + + if(tc->V1 == NULL || tc->V2 == NULL) { + tc->PrimType = -1; + return tc->Error = ACTC_PRIM_COMPLETE; + } + + ACTC_INFO(printf("looking for edge %u, %u\n", tc->V1->V, tc->V2->V);) + + wasFoundReversed = 0; + + if(findEdge(tc->V1, tc->V2, &edge) != 0) { + wasEdgeFound = 1; + } else if(!tc->HonorWinding) { + wasFoundReversed = 1; + if(findEdge(tc->V2, tc->V1, &edge) != 0) { + wasEdgeFound = 1; + } + } + + if(!wasEdgeFound) { + tc->PrimType = -1; + return tc->Error = ACTC_PRIM_COMPLETE; + } + + thirdVertex = edge->Triangles[edge->TriangleCount - 1].FinalVert; + + ACTC_INFO(printf("third vertex = %u\n", thirdVertex->V);) + *vertReturn = thirdVertex->V; + + if(wasFoundReversed) { + ACTC_CHECK(unmapEdgeTriangle(tc, edge, thirdVertex)); + ACTC_CHECK(unmapEdgeTriangleByVerts(tc, tc->V1, thirdVertex, tc->V2)); + ACTC_CHECK(unmapEdgeTriangleByVerts(tc, thirdVertex, tc->V2, tc->V1)); + ACTC_CHECK(unmapVertexEdge(tc, tc->V2, tc->V1)); + ACTC_CHECK(unmapVertexEdge(tc, tc->V1, thirdVertex)); + ACTC_CHECK(unmapVertexEdge(tc, thirdVertex, tc->V2)); + } else { + ACTC_CHECK(unmapEdgeTriangle(tc, edge, thirdVertex)); + ACTC_CHECK(unmapEdgeTriangleByVerts(tc, tc->V2, thirdVertex, tc->V1)); + ACTC_CHECK(unmapEdgeTriangleByVerts(tc, thirdVertex, tc->V1, tc->V2)); + ACTC_CHECK(unmapVertexEdge(tc, tc->V1, tc->V2)); + ACTC_CHECK(unmapVertexEdge(tc, tc->V2, thirdVertex)); + ACTC_CHECK(unmapVertexEdge(tc, thirdVertex, tc->V1)); + } + ACTC_CHECK(decVertexValence(tc, &tc->V1)); + ACTC_CHECK(decVertexValence(tc, &tc->V2)); + ACTC_CHECK(decVertexValence(tc, &thirdVertex)); + + if(tc->PrimType == ACTC_PRIM_FAN) { + tc->V2 = thirdVertex; + } else /* PRIM_STRIP */ { + if(tc->CurWindOrder == ACTC_FWD_ORDER) + tc->V1 = thirdVertex; + else + tc->V2 = thirdVertex; + tc->CurWindOrder = !tc->CurWindOrder; + } + + tc->VerticesSoFar++; + return ACTC_NO_ERROR; +} + +int actcTrianglesToPrimitives(ACTCData *tc, int triangleCount, + uint (*triangles)[3], int primTypes[], int primLengths[], uint vertices[], + int maxBatchSize) +{ + int r; + int curTriangle; + int curPrimitive; + uint curVertex; + int prim; + uint v1, v2, v3; + int lastPrim; + int passesWithoutPrims; + int trisSoFar; + + if(tc->IsInputting) { + ACTC_DEBUG(fprintf(stderr, "actcTrianglesToPrimitives : within BeginInput/" + "EndInput\n");) + return tc->Error = ACTC_DURING_INPUT; + } + if(tc->IsOutputting) { + ACTC_DEBUG(fprintf(stderr, "actcTrianglesToPrimitives : within" + "BeginOutput/EndOutput\n");) + return tc->Error = ACTC_DURING_OUTPUT; + } + curTriangle = 0; + curPrimitive = 0; + curVertex = 0; + passesWithoutPrims = 0; + + actcMakeEmpty(tc); + + ACTC_CHECK(actcBeginInput(tc)); + trisSoFar = 0; + while(curTriangle < triangleCount) { + r = actcAddTriangle(tc, triangles[curTriangle][0], + triangles[curTriangle][1], triangles[curTriangle][2]); + trisSoFar++; + curTriangle++; + if((trisSoFar >= maxBatchSize) || + (r == ACTC_ALLOC_FAILED && curTriangle != triangleCount) || + (r == ACTC_NO_ERROR && curTriangle == triangleCount)) { + + /* drain what we got */ + trisSoFar = 0; + ACTC_CHECK(actcEndInput(tc)); + ACTC_CHECK(actcBeginOutput(tc)); + lastPrim = curPrimitive; + while((prim = actcStartNextPrim(tc, &v1, &v2)) != ACTC_DATABASE_EMPTY) { + ACTC_CHECK(prim); + primTypes[curPrimitive] = prim; + primLengths[curPrimitive] = 2; + vertices[curVertex++] = v1; + vertices[curVertex++] = v2; + while((r = actcGetNextVert(tc, &v3)) != ACTC_PRIM_COMPLETE) { + ACTC_CHECK(r); + vertices[curVertex++] = v3; + primLengths[curPrimitive]++; + } + curPrimitive++; + } + ACTC_CHECK(actcEndOutput(tc)); + if(r == ACTC_ALLOC_FAILED && curPrimitive == lastPrim) { + if(passesWithoutPrims == 0) { + /* not enough memory to add a triangle and */ + /* nothing in the database, better free everything */ + /* and try again */ + actcMakeEmpty(tc); + } else { + /* cleaned up and STILL couldn't get a triangle in; */ + /* give up */ + return tc->Error = ACTC_ALLOC_FAILED; + } + passesWithoutPrims++; + } + ACTC_CHECK(actcBeginInput(tc)); + } else + ACTC_CHECK(r); + if(r == ACTC_ALLOC_FAILED) + curTriangle--; + } + ACTC_CHECK(actcEndInput(tc)); + + actcMakeEmpty(tc); + + return curPrimitive; +} + +/* vi:tabstop=8 + */ diff --git a/Graphics/tc.h b/Graphics/tc.h new file mode 100644 index 0000000000..63799308c7 --- /dev/null +++ b/Graphics/tc.h @@ -0,0 +1,77 @@ +/* + * $Header: /cvsroot/gmsh/Graphics/tc.h,v 1.1 2006-08-10 15:29:26 geuzaine Exp $ + */ + +#if !defined(_ACTC_H_) +#define _ACTC_H_ + +#include <sys/types.h> + +typedef struct _ACTCData ACTCData; + +/* + Abbreviated: + vertex vert + primitive prim + maximum max + minimum min + parameter param + */ + +#define ACTC_NO_ERROR 0 +#define ACTC_ALLOC_FAILED -0x2000 +#define ACTC_DURING_INPUT -0x2001 +#define ACTC_DURING_OUTPUT -0x2002 +#define ACTC_IDLE -0x2003 +#define ACTC_INVALID_VALUE -0x2004 +#define ACTC_DATABASE_EMPTY -0x2005 +#define ACTC_DATABASE_CORRUPT -0x2006 +#define ACTC_PRIM_COMPLETE -0x2007 + +#define ACTC_OUT_MIN_FAN_VERTS 0x1000 +#define ACTC_OUT_HONOR_WINDING 0x1001 +#define ACTC_OUT_MAX_PRIM_VERTS 0x1004 +#define ACTC_IN_MIN_VERT 0x1005 +#define ACTC_IN_MAX_VERT 0x1006 +#define ACTC_IN_MAX_VERT_SHARING 0x1007 +#define ACTC_IN_MAX_EDGE_SHARING 0x1008 +#define ACTC_MINOR_VERSION 0x1009 +#define ACTC_MAJOR_VERSION 0x1010 + +#define ACTC_PRIM_FAN 0x2000 +#define ACTC_PRIM_STRIP 0x2001 + +#define ACTC_TRUE 1 +#define ACTC_FALSE 0 + +ACTCData *actcNew(void); +int actcParami(ACTCData *tc, int param, int value); +int actcGetParami(ACTCData *tc, int param, int *value); +int actcParamu(ACTCData *tc, int param, uint value); +int actcGetParamu(ACTCData *tc, int param, uint *value); +int actcGetError(ACTCData *tc); +int actcMakeEmpty(ACTCData *tc); +void actcDelete(ACTCData *tc); +void actcDumpState(ACTCData *tc, FILE *fp); + +int actcBeginInput(ACTCData *tc); +int actcGetIsDuringInput(ACTCData *tc); +int actcAddTriangle(ACTCData *tc, uint v1, uint v2, uint v3); +int actcEndInput(ACTCData *tc); + +int actcBeginOutput(ACTCData *tc); +int actcGetIsDuringOutput(ACTCData *tc); +int actcStartNextPrim(ACTCData *tc, uint *v1Return, uint *v2Return); +int actcGetNextVert(ACTCData *tc, uint *vReturn); +int actcEndOutput(ACTCData *tc); + +int actcGetMemoryAllocation(ACTCData *tc, size_t *bytesAllocated); + +int actcTrianglesToPrimitives(ACTCData *tc, int triangleCount, + uint (*triangles)[3], int primTypes[], int primLengths[], uint vertices[], + int maxBatchSize); + +#endif /* _ACTC_H_ */ + +/* vi:tabstop=8 + */ diff --git a/Mesh/DiscreteSurface.cpp b/Mesh/DiscreteSurface.cpp index ce8db9341d..0027eff425 100644 --- a/Mesh/DiscreteSurface.cpp +++ b/Mesh/DiscreteSurface.cpp @@ -1,4 +1,4 @@ -// $Id: DiscreteSurface.cpp,v 1.42 2006-08-06 22:58:49 geuzaine Exp $ +// $Id: DiscreteSurface.cpp,v 1.43 2006-08-10 15:29:26 geuzaine Exp $ // // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle // @@ -208,8 +208,6 @@ void Mesh_To_BDS(Mesh *M) } -extern int addMeshPartition(int Num, Mesh *M); - void BDS_To_Mesh_2(Mesh *M) { Msg(STATUS2, "Moving surface mesh into old structure"); @@ -273,7 +271,6 @@ void BDS_To_Mesh_2(Mesh *M) Surface *s = FindSurface(g->classif_tag, M); if(s) { simp->iEnt = g->classif_tag; - simp->iPart = addMeshPartition((*it)->partition, M); } else Msg(GERROR, "Impossible to find surface %d", g->classif_tag); @@ -300,7 +297,6 @@ void BDS_To_Mesh_2(Mesh *M) Volume *v = FindVolume(g->classif_tag, M); if(v) { simp->iEnt = g->classif_tag; - simp->iPart = addMeshPartition((*it)->partition, M); } else Msg(GERROR, "Error in BDS"); diff --git a/Mesh/Mesh.h b/Mesh/Mesh.h index bf707b3b35..8d3b9c0426 100644 --- a/Mesh/Mesh.h +++ b/Mesh/Mesh.h @@ -363,7 +363,6 @@ void Init_Mesh0(); void Init_Mesh(); void GetStatistics(double s[50], double quality[3][100]=0); -void GetDefaultMeshFileName(int Type, char *name); void Maillage_Dimension_1(); void Maillage_Dimension_2(); diff --git a/doc/CREDITS b/doc/CREDITS index 6aa5c346df..74e23949a3 100644 --- a/doc/CREDITS +++ b/doc/CREDITS @@ -1,4 +1,4 @@ -$Id: CREDITS,v 1.35 2006-06-08 12:32:08 geuzaine Exp $ +$Id: CREDITS,v 1.36 2006-08-10 15:29:26 geuzaine Exp $ Gmsh is copyright (C) 1997-2006 @@ -55,6 +55,9 @@ copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. This software is provided "as is" without express or implied warranty. +This product includes software developed by Brad Grantham and +Applied Conjecture. (Graphics/tp.*) + The colorbar widget (Fltk/Colorbar_Window.cpp) was inspired by code from the Vis5d program for visualizing five dimensional gridded data sets, copyright (C) 1990-1995, Bill Hibbard, Brian Paul, Dave Santek, -- GitLab