00001
00002
00003
00004
00005
00006
00007 #include <stdlib.h>
00008 #include <stdio.h>
00009 #include <setjmp.h>
00010 #include <math.h>
00011 #include <windows.h>
00012
00013 #include "struct.h"
00014 #include "dstruct.h"
00015
00016 #include "chull.h"
00017
00018 jmp_buf jmp_buf_here;
00019
00020
00021 typedef BOOL bool;
00022
00023 typedef struct tVertexStructure tsVertex;
00024 typedef tsVertex *tVertex;
00025
00026 typedef struct tEdgeStructure tsEdge;
00027 typedef tsEdge *tEdge;
00028
00029 typedef struct tFaceStructure tsFace;
00030 typedef tsFace *tFace;
00031
00032 struct tVertexStructure {
00033 int v[3];
00034 int vnum;
00035 int OFXid;
00036 tEdge duplicate;
00037 bool onhull;
00038 bool mark;
00039 tVertex next, prev;
00040 };
00041
00042 struct tEdgeStructure {
00043 tFace adjface[2];
00044 tVertex endpts[2];
00045 tFace newface;
00046 bool HULL_DELETE;
00047 tEdge next, prev;
00048 };
00049
00050 struct tFaceStructure {
00051 tEdge edge[3];
00052 tVertex vertex[3];
00053 bool visible;
00054 tFace next, prev;
00055 };
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 #define SWAP(t,x,y) { t = x; x = y; y = t; }
00066
00067
00068 #define NEW(p,type) if ((p=(type *) malloc (sizeof(type))) == NULL) {\
00069 longjmp(jmp_buf_here,-1);\
00070 }
00071
00072 #define FREE(p) if (p) { free ((char *) p); p = NULL; }
00073
00074
00075 #define HULL_ADD( head, p ) if ( head ) { \
00076 p->next = head; \
00077 p->prev = head->prev; \
00078 head->prev = p; \
00079 p->prev->next = p; \
00080 } \
00081 else { \
00082 head = p; \
00083 head->next = head->prev = p; \
00084 }
00085
00086 #define HULL_DELETE( head, p ) if ( head ) { \
00087 if ( head == head->next ) \
00088 head = NULL; \
00089 else if ( p == head ) \
00090 head = head->next; \
00091 p->next->prev = p->prev; \
00092 p->prev->next = p->next; \
00093 FREE( p ); \
00094 }
00095
00097
00098 #define DESELECTED 0
00099 #define SELECTED 1
00100 #define MINUNIT 2048L // was 1024 trying larger to prevent error
00101 #define MAXUNIT 33554432L
00102
00103 #ifndef min
00104 #define min(a,b) ( ((a) < (b)) ? (a) : (b) )
00105 #endif
00106 #ifndef max
00107 #define max(a,b) ( ((a) > (b)) ? (a) : (b) )
00108 #endif
00109
00110 BOOL DoubleTriangle( void );
00111 void ConstructHull( void );
00112 tVertex MakeNullVertex( void );
00113 void DeleteTemporaryStructures(void);
00114
00115
00116 #define X 0
00117 #define Y 1
00118 #define Z 2
00119
00120
00121 tVertex vertices = NULL;
00122 tEdge edges = NULL;
00123 tFace faces = NULL;
00124
00125 static HWND hParent;
00126 static HINSTANCE hThisInstance;
00127
00128 #if __WATCOMC__
00129 int APIENTRY LibMain(HANDLE hDLL, DWORD dwReason, LPVOID lpReserved){
00130 #else
00131 BOOL WINAPI DllMain(HANDLE hDLL, DWORD dwReason, LPVOID lpReserved){
00132 #endif
00133 switch (dwReason) {
00134 case DLL_PROCESS_ATTACH: {
00135 hThisInstance=hDLL;
00136 if(hDLL == NULL)MessageBox ( GetFocus()," NULL instance",NULL, MB_OK);
00137 break;
00138 }
00139 case DLL_PROCESS_DETACH:
00140 break;
00141 }
00142 return TRUE;
00143 }
00144
00145 BOOL _Xmodeler
00146 (HWND parent_window,HWND info_window,X__STRUCTURE *lpevi){
00147 char text_string[255],name_string[255];
00148 lpEVI=lpevi;
00149 hParent=parent_window;
00150 LoadString(hThisInstance,IDX_STRING2,text_string,256);
00151 LoadString(hThisInstance,IDX_STRING1,name_string,256);
00152 if(MessageBox(hParent,text_string,name_string,MB_OKCANCEL)
00153 == IDCANCEL)return FALSE;
00154 else{
00155 HCURSOR hSave;
00156 vertex *vp;
00157 long i,maxdim;
00158 long xmin=MAXUNIT,xmax=-MAXUNIT,ymin=MAXUNIT,ymax=-MAXUNIT,zmin=MAXUNIT,zmax=-MAXUNIT;
00159 double scale;
00160 if(NvertSelect < 4 || NvertSelect > 32000)return FALSE;
00161 hSave=SetCursor(LoadCursor(NULL,IDC_WAIT));
00162 vp=MainVp; for(i=0;i<Nvert;i++){
00163 if(vp->status == SELECTED){
00164 if(vp->xyz[0] < xmin)xmin=vp->xyz[0];
00165 if(vp->xyz[1] < ymin)ymin=vp->xyz[1];
00166 if(vp->xyz[2] < zmin)zmin=vp->xyz[2];
00167 if(vp->xyz[0] > xmax)xmax=vp->xyz[0];
00168 if(vp->xyz[1] > ymax)ymax=vp->xyz[1];
00169 if(vp->xyz[2] > zmax)zmax=vp->xyz[2];
00170 }
00171 vp++;
00172 }
00173 maxdim=max(xmax-xmin,ymax-ymin);
00174 maxdim=max(maxdim,zmax-zmin);
00175 if(xmax-xmin > MINUNIT &&
00176 ymax-ymin > MINUNIT &&
00177 zmax-zmin > MINUNIT){
00178 tVertex v;
00179 tEdge e;
00180 tFace f;
00181 int vnum=0;
00182 scale=(double)MINUNIT/(double)maxdim;
00183 vp=MainVp; for(i=0;i<Nvert;i++){
00184 if(vp->status == SELECTED){
00185 v=MakeNullVertex();
00186 v->v[X] = (long)((double)vp->xyz[0]*scale);
00187 v->v[Y] = (long)((double)vp->xyz[1]*scale);
00188 v->v[Z] = (long)((double)vp->xyz[2]*scale);
00189 v->vnum=vnum++;
00190 }
00191 vp++;
00192 }
00193
00194
00195
00196
00197 if(setjmp(jmp_buf_here) != 0){
00198 DeleteTemporaryStructures();
00199 SetCursor(hSave);
00200 LoadString(hThisInstance,IDX_STRING3,text_string,256);
00201 MessageBox(hParent,text_string,name_string,MB_OKCANCEL);
00202 return FALSE;
00203 }
00204 if(DoubleTriangle()){
00205 long nf=0,ne=0,nv=0;
00206 ConstructHull();
00207
00208 f=faces; if(f != NULL)do {
00209 nf++;
00210 f = f->next;
00211 } while(f != faces);
00212 e = edges;if(e != NULL)do {
00213 ne++;
00214 e = e->next;
00215 } while (e != edges);
00216 v = vertices; if(v != NULL)do {
00217 nv++;
00218 v = v->next;
00219 } while (v != vertices);
00220
00221
00222
00223
00224
00225 if(!UpdateVertexHeap(Nvert+nv))goto CANTDO;
00226 if(!UpdateEdgeHeap(Nedge+ne))goto CANTDO;
00227 if(!UpdateFaceHeap(Nface+ne))goto CANTDO;
00228 v = vertices; if(v != NULL)do {
00229 CreateVertex();
00230 vp=(MainVp+Nvert-1);
00231 vp->xyz[0]=(long)((double)(v->v[X])/scale);
00232 vp->xyz[1]=(long)((double)(v->v[Y])/scale);
00233 vp->xyz[2]=(long)((double)(v->v[Z])/scale);
00234 vp->status=DESELECTED;
00235 v->OFXid = Nvert-1;
00236 NvertDeselect++; NvertSelect--;
00237 nv++;
00238 v = v->next;
00239 } while (v != vertices);
00240
00241 e = edges;
00242 if(e != NULL)do {
00243 CreateEdge(e->endpts[0]->OFXid,e->endpts[1]->OFXid);
00244 e = e->next;
00245 } while (e != edges);
00246 f = faces;
00247 if(f != NULL)do {
00248 CreateFace(f->vertex[0]->OFXid,f->vertex[1]->OFXid,f->vertex[2]->OFXid);
00249 f = f->next;
00250 } while(f != faces);
00251 CANTDO:;
00252 }
00253 DeleteTemporaryStructures();
00254 SetCursor(hSave);
00255 LoadString(hThisInstance,IDX_STRING3,text_string,256);
00256 MessageBox(hParent,text_string,name_string,MB_OKCANCEL);
00257 }
00258 else{
00259 LoadString(hThisInstance,IDX_STRING4,text_string,256);
00260 MessageBox(hParent,text_string,name_string,MB_OKCANCEL);
00261 SetCursor(hSave);
00262 }
00263 }
00264 return TRUE;
00265 }
00266
00267 void DeleteTemporaryStructures(void){
00268 tEdge e,te;
00269 tFace f,tf;
00270 tVertex v,tv;
00271 f=faces;
00272 if(f != NULL)do {
00273 tf = f;
00274 f = f->next;
00275 FREE(tf)
00276 } while(f != faces);
00277 e = edges;
00278 if(e != NULL)do {
00279 te = e;
00280 e = e->next;
00281 FREE(te)
00282 } while (e != edges);
00283 v = vertices;
00284 if(v != NULL)do {
00285 tv = v;
00286 v = v->next;
00287 FREE(tv)
00288 } while (v != vertices);
00289 return;
00290 }
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319 #define ONHULL TRUE
00320 #define REMOVED TRUE
00321 #define VISIBLE TRUE
00322 #define PROCESSED TRUE
00323 #define SAFE 1000000
00324
00325
00326 void ReadVertices( void );
00327 void Print( void );
00328 void SubVec( int a[3], int b[3], int c[3]);
00329 bool HULL_ADDOne( tVertex p );
00330 int VolumeSign(tFace f, tVertex p);
00331 int Volumei( tFace f, tVertex p );
00332 tFace MakeConeFace( tEdge e, tVertex p );
00333 void MakeCcw( tFace f, tEdge e, tVertex p );
00334 tEdge MakeNullEdge( void );
00335 tFace MakeNullFace( void );
00336 tFace MakeFace( tVertex v0, tVertex v1, tVertex v2, tFace f );
00337 void CleanUp( void );
00338 void CleanEdges( void );
00339 void CleanFaces( void );
00340 void CleanVertices( void );
00341 bool Collinear( tVertex a, tVertex b, tVertex c );
00342
00343
00344
00345
00346 tVertex MakeNullVertex( void ){
00347 tVertex v;
00348 NEW( v, tsVertex );
00349 v->duplicate = NULL;
00350 v->onhull = !ONHULL;
00351 v->mark = !PROCESSED;
00352 HULL_ADD( vertices, v );
00353
00354 return v;
00355 }
00356
00357
00358
00359
00360 void SubVec( int a[3], int b[3], int c[3]){
00361 int i;
00362
00363 for( i=0; i < 2; i++ )
00364 c[i] = a[i] - b[i];
00365
00366 }
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377 BOOL DoubleTriangle( void ){
00378 tVertex v0, v1, v2, v3, t;
00379 tFace f0, f1 = NULL;
00380 tEdge e0, e1, e2, s;
00381 int vol;
00382
00383
00384 v0 = vertices;
00385 while ( Collinear( v0, v0->next, v0->next->next ) )
00386 if ( ( v0 = v0->next ) == vertices )
00387 return FALSE;
00388 v1 = v0->next;
00389 v2 = v1->next;
00390
00391
00392 v0->mark = PROCESSED;
00393 v1->mark = PROCESSED;
00394 v2->mark = PROCESSED;
00395
00396
00397 f0 = MakeFace( v0, v1, v2, f1 );
00398 f1 = MakeFace( v2, v1, v0, f0 );
00399
00400
00401 f0->edge[0]->adjface[1] = f1;
00402 f0->edge[1]->adjface[1] = f1;
00403 f0->edge[2]->adjface[1] = f1;
00404 f1->edge[0]->adjface[1] = f0;
00405 f1->edge[1]->adjface[1] = f0;
00406 f1->edge[2]->adjface[1] = f0;
00407
00408
00409 v3 = v2->next;
00410 vol = VolumeSign( f0, v3 );
00411 while ( !vol ) {
00412 if ( ( v3 = v3->next ) == v0 )
00413 return FALSE;
00414 vol = VolumeSign( f0, v3 );
00415 }
00416
00417
00418 vertices = v3;
00419 return TRUE;
00420 }
00421
00422
00423
00424
00425
00426
00427 void ConstructHull( void ){
00428 tVertex v, vnext;
00429 int vol;
00430 bool changed;
00431 v = vertices;
00432 do {
00433 vnext = v->next;
00434 if ( !v->mark ) {
00435 v->mark = PROCESSED;
00436 changed = HULL_ADDOne( v );
00437 CleanUp();
00438 }
00439 v = vnext;
00440 } while ( v != vertices );
00441 }
00442
00443
00444
00445
00446
00447
00448
00449
00450 bool HULL_ADDOne( tVertex p )
00451 {
00452 tFace f;
00453 tEdge e, temp;
00454 int vol;
00455 bool vis = FALSE;
00456
00457
00458 f = faces;
00459 do {
00460 vol = VolumeSign( f, p );
00461 if ( vol < 0 ) {
00462 f->visible = VISIBLE;
00463 vis = TRUE;
00464 }
00465 f = f->next;
00466 } while ( f != faces );
00467
00468
00469 if ( !vis ) {
00470 p->onhull = !ONHULL;
00471 return FALSE;
00472 }
00473
00474
00475
00476 e = edges;
00477 do {
00478 temp = e->next;
00479 if ( e->adjface[0]->visible && e->adjface[1]->visible )
00480
00481 e->HULL_DELETE = REMOVED;
00482 else if ( e->adjface[0]->visible || e->adjface[1]->visible )
00483
00484 e->newface = MakeConeFace( e, p );
00485 e = temp;
00486 } while ( e != edges );
00487 return TRUE;
00488 }
00489
00490
00491
00492
00493
00494
00495
00496
00497 int VolumeSign( tFace f, tVertex p ){
00498 double vol;
00499 int voli;
00500 double ax, ay, az, bx, by, bz, cx, cy, cz;
00501
00502 ax = f->vertex[0]->v[X] - p->v[X];
00503 ay = f->vertex[0]->v[Y] - p->v[Y];
00504 az = f->vertex[0]->v[Z] - p->v[Z];
00505 bx = f->vertex[1]->v[X] - p->v[X];
00506 by = f->vertex[1]->v[Y] - p->v[Y];
00507 bz = f->vertex[1]->v[Z] - p->v[Z];
00508 cx = f->vertex[2]->v[X] - p->v[X];
00509 cy = f->vertex[2]->v[Y] - p->v[Y];
00510 cz = f->vertex[2]->v[Z] - p->v[Z];
00511
00512 vol = ax * (by*cz - bz*cy)
00513 + ay * (bz*cx - bx*cz)
00514 + az * (bx*cy - by*cx);
00515
00516
00517 if ( vol > 0.5 ) return 1;
00518 else if ( vol < -0.5 ) return -1;
00519 else return 0;
00520 }
00521
00522
00523
00524 int Volumei( tFace f, tVertex p ){
00525 int vol;
00526 int ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz;
00527
00528 ax = f->vertex[0]->v[X] - p->v[X];
00529 ay = f->vertex[0]->v[Y] - p->v[Y];
00530 az = f->vertex[0]->v[Z] - p->v[Z];
00531 bx = f->vertex[1]->v[X] - p->v[X];
00532 by = f->vertex[1]->v[Y] - p->v[Y];
00533 bz = f->vertex[1]->v[Z] - p->v[Z];
00534 cx = f->vertex[2]->v[X] - p->v[X];
00535 cy = f->vertex[2]->v[Y] - p->v[Y];
00536 cz = f->vertex[2]->v[Z] - p->v[Z];
00537
00538 vol = (ax * (by*cz - bz*cy)
00539 + ay * (bz*cx - bx*cz)
00540 + az * (bx*cy - by*cx));
00541
00542 return vol;
00543 }
00544
00545
00546
00547
00548
00549
00550 tFace MakeConeFace( tEdge e, tVertex p )
00551 {
00552 tEdge new_edge[2];
00553 tFace new_face;
00554 int i, j;
00555
00556
00557 for ( i=0; i < 2; ++i )
00558
00559 if ( !( new_edge[i] = e->endpts[i]->duplicate) ) {
00560
00561 new_edge[i] = MakeNullEdge();
00562 new_edge[i]->endpts[0] = e->endpts[i];
00563 new_edge[i]->endpts[1] = p;
00564 e->endpts[i]->duplicate = new_edge[i];
00565 }
00566
00567
00568 new_face = MakeNullFace();
00569 new_face->edge[0] = e;
00570 new_face->edge[1] = new_edge[0];
00571 new_face->edge[2] = new_edge[1];
00572 MakeCcw( new_face, e, p );
00573
00574
00575 for ( i=0; i < 2; ++i )
00576 for ( j=0; j < 2; ++j )
00577
00578 if ( !new_edge[i]->adjface[j] ) {
00579 new_edge[i]->adjface[j] = new_face;
00580 break;
00581 }
00582
00583 return new_face;
00584 }
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597 void MakeCcw( tFace f, tEdge e, tVertex p )
00598 {
00599 tFace fv;
00600 int i;
00601 tEdge s;
00602
00603 if ( e->adjface[0]->visible )
00604 fv = e->adjface[0];
00605 else fv = e->adjface[1];
00606
00607
00608
00609 for ( i=0; fv->vertex[i] != e->endpts[0]; ++i )
00610 ;
00611
00612 if ( fv->vertex[ (i+1) % 3 ] != e->endpts[1] ) {
00613 f->vertex[0] = e->endpts[1];
00614 f->vertex[1] = e->endpts[0];
00615 }
00616 else {
00617 f->vertex[0] = e->endpts[0];
00618 f->vertex[1] = e->endpts[1];
00619 SWAP( s, f->edge[1], f->edge[2] );
00620 }
00621
00622
00623
00624
00625 f->vertex[2] = p;
00626 }
00627
00628
00629
00630
00631
00632 tEdge MakeNullEdge( void )
00633 {
00634 tEdge e;
00635
00636 NEW( e, tsEdge );
00637 e->adjface[0] = e->adjface[1] = e->newface = NULL;
00638 e->endpts[0] = e->endpts[1] = NULL;
00639 e->HULL_DELETE = !REMOVED;
00640 HULL_ADD( edges, e );
00641 return e;
00642 }
00643
00644
00645
00646
00647
00648
00649 tFace MakeNullFace( void ){
00650 tFace f;
00651 int i;
00652
00653 NEW( f, tsFace);
00654 for ( i=0; i < 3; ++i ) {
00655 f->edge[i] = NULL;
00656 f->vertex[i] = NULL;
00657 }
00658 f->visible = !VISIBLE;
00659 HULL_ADD( faces, f );
00660 return f;
00661 }
00662
00663
00664
00665
00666
00667 tFace MakeFace( tVertex v0, tVertex v1, tVertex v2, tFace fold ){
00668 tFace f;
00669 tEdge e0, e1, e2;
00670
00671
00672 if( !fold ) {
00673 e0 = MakeNullEdge();
00674 e1 = MakeNullEdge();
00675 e2 = MakeNullEdge();
00676 }
00677 else {
00678 e0 = fold->edge[2];
00679 e1 = fold->edge[1];
00680 e2 = fold->edge[0];
00681 }
00682 e0->endpts[0] = v0; e0->endpts[1] = v1;
00683 e1->endpts[0] = v1; e1->endpts[1] = v2;
00684 e2->endpts[0] = v2; e2->endpts[1] = v0;
00685
00686
00687 f = MakeNullFace();
00688 f->edge[0] = e0; f->edge[1] = e1; f->edge[2] = e2;
00689 f->vertex[0] = v0; f->vertex[1] = v1; f->vertex[2] = v2;
00690
00691
00692 e0->adjface[0] = e1->adjface[0] = e2->adjface[0] = f;
00693
00694 return f;
00695 }
00696
00697
00698
00699
00700
00701
00702 void CleanUp( void ){
00703 CleanEdges();
00704 CleanFaces();
00705 CleanVertices();
00706 }
00707
00708
00709
00710
00711
00712
00713 void CleanEdges( void ){
00714 tEdge e;
00715 tEdge t;
00716
00717
00718
00719 e = edges;
00720 do {
00721 if ( e->newface ) {
00722 if ( e->adjface[0]->visible )
00723 e->adjface[0] = e->newface;
00724 else e->adjface[1] = e->newface;
00725 e->newface = NULL;
00726 }
00727 e = e->next;
00728 } while ( e != edges );
00729
00730
00731 while ( edges && edges->HULL_DELETE ) {
00732 e = edges;
00733 HULL_DELETE( edges, e );
00734 }
00735 e = edges->next;
00736 do {
00737 if ( e->HULL_DELETE ) {
00738 t = e;
00739 e = e->next;
00740 HULL_DELETE( edges, t );
00741 }
00742 else e = e->next;
00743 } while ( e != edges );
00744 }
00745
00746
00747
00748
00749 void CleanFaces( void ){
00750 tFace f;
00751 tFace t;
00752 while ( faces && faces->visible ) {
00753 f = faces;
00754 HULL_DELETE( faces, f );
00755 }
00756 f = faces->next;
00757 do {
00758 if ( f->visible ) {
00759 t = f;
00760 f = f->next;
00761 HULL_DELETE( faces, t );
00762 }
00763 else f = f->next;
00764 } while ( f != faces );
00765 }
00766
00767
00768
00769
00770
00771
00772 void CleanVertices( void ){
00773 tEdge e;
00774 tVertex v, t;
00775
00776
00777 e = edges;
00778 do {
00779 e->endpts[0]->onhull = e->endpts[1]->onhull = ONHULL;
00780 e = e->next;
00781 } while (e != edges);
00782
00783
00784
00785 while ( vertices && vertices->mark && !vertices->onhull ) {
00786 v = vertices;
00787 HULL_DELETE( vertices, v );
00788 }
00789 v = vertices->next;
00790 do {
00791 if ( v->mark && !v->onhull ) {
00792 t = v;
00793 v = v->next;
00794 HULL_DELETE( vertices, t )
00795 }
00796 else v = v->next;
00797 } while ( v != vertices );
00798
00799
00800 v = vertices;
00801 do {
00802 v->duplicate = NULL;
00803 v->onhull = !ONHULL;
00804 v = v->next;
00805 } while ( v != vertices );
00806 }
00807
00808
00809
00810
00811
00812 bool Collinear( tVertex a, tVertex b, tVertex c )
00813 {
00814 return
00815 ( c->v[Z] - a->v[Z] ) * ( b->v[Y] - a->v[Y] ) -
00816 ( b->v[Z] - a->v[Z] ) * ( c->v[Y] - a->v[Y] ) == 0
00817 && ( b->v[Z] - a->v[Z] ) * ( c->v[X] - a->v[X] ) -
00818 ( b->v[X] - a->v[X] ) * ( c->v[Z] - a->v[Z] ) == 0
00819 && ( b->v[X] - a->v[X] ) * ( c->v[Y] - a->v[Y] ) -
00820 ( b->v[Y] - a->v[Y] ) * ( c->v[X] - a->v[X] ) == 0 ;
00821 }
00822