BOOLEAN.C

Go to the documentation of this file.
00001 /* --
00002 OpenFX version 2.0 - Modelling, Animation and Rendering Package
00003 Copyright (C) 2000 - 2007 OpenFX Development Team
00004 -- */
00005 
00006 /*  BOOLEAN.C  */
00007 
00008 #include <stdlib.h>
00009 #include <stdio.h>
00010 #include <math.h>
00011 #include <windows.h>
00012 
00013 #include "struct.h"
00014 #include "dstruct.h"
00015 
00016 #define DLG_CUT                     600
00017 #define DLG_CUT_SPLIT_Y             601
00018 #define DLG_CUT_SPLIT_N             602
00019 #define DLG_CUT_BOTH                603
00020 #define DLG_CUT_WORKPIECE           604
00021 
00022 #define IDX_MESSAGE1                700
00023 
00024 //FILE *debug;
00025 
00026 #include "boolean.h"
00027 
00028 #define DESELECTED 0
00029 #define SELECTED   1
00030 #define HIDDEN     2
00031 #define INEDITOR   3
00032 
00033 static HWND      hParent;
00034 static HINSTANCE hThisInstance;
00035 
00036 
00037 #if __WATCOMC__
00038 int APIENTRY LibMain(HANDLE hDLL, DWORD dwReason, LPVOID lpReserved){
00039 #else
00040 BOOL WINAPI DllMain(HANDLE hDLL, DWORD dwReason, LPVOID lpReserved){
00041 #endif
00042   switch (dwReason) {
00043     case DLL_PROCESS_ATTACH: {
00044       hThisInstance=hDLL;
00045       if(hDLL == NULL)MessageBox( GetFocus()," NULL instance",NULL, MB_OK);
00046       break;
00047     }
00048     case DLL_PROCESS_DETACH:
00049       break;
00050   }
00051   return TRUE;
00052 }
00053 
00054 #if __SC__
00055 #pragma startaddress(DllMain)
00056 #endif
00057 
00058 static BOOL CALLBACK BooleanDlgProc(HWND hwnd, UINT msg,
00059                              WPARAM wparam, LPARAM lparam){
00060  BOOL err;
00061  int i;
00062  static struct bp {BOOL sp,al;} *dp;
00063  switch( msg ) {
00064    case WM_INITDIALOG:
00065      dp=(struct bp *)lparam;
00066      if(dp->sp)SendDlgItemMessage(hwnd,DLG_CUT_SPLIT_Y,BM_SETCHECK,TRUE,0);
00067      else      SendDlgItemMessage(hwnd,DLG_CUT_SPLIT_N,BM_SETCHECK,TRUE,0);
00068      if(dp->al)SendDlgItemMessage(hwnd,DLG_CUT_BOTH,BM_SETCHECK,TRUE,0);
00069      else      SendDlgItemMessage(hwnd,DLG_CUT_WORKPIECE,BM_SETCHECK,TRUE,0);
00070      CentreDlgOnS(hwnd);
00071      return (TRUE);
00072    case WM_COMMAND:
00073       switch(LOWORD(wparam)){
00074         case IDCANCEL:
00075           EndDialog(hwnd,FALSE);
00076           return(TRUE);
00077         case IDOK:
00078           if(SendDlgItemMessage(hwnd,DLG_CUT_SPLIT_Y,BM_GETCHECK,0,0))
00079              dp->sp=TRUE; else dp->sp=FALSE;
00080           if(SendDlgItemMessage(hwnd,DLG_CUT_BOTH,BM_GETCHECK,0,0))
00081              dp->al=TRUE; else dp->al=FALSE;
00082           EndDialog(hwnd,TRUE);
00083           return(TRUE);
00084         default:
00085           break;
00086       }
00087       break;
00088     default: break;
00089  }
00090  return(FALSE);
00091 }
00092 
00093 BOOL _Xmodeler
00094  (HWND parent_window,HWND info_window,X__STRUCTURE *lpevi){
00095  HCURSOR hSave;
00096  int type,split;
00097  struct bp {BOOL sp,al;} d;
00098  lpEVI=lpevi;
00099  hParent=parent_window;
00100  d.sp=TRUE; d.al=TRUE;
00101  if(DialogBoxParam(hThisInstance,MAKEINTRESOURCE(DLG_CUT),hParent,
00102              (DLGPROC)BooleanDlgProc,(LPARAM)&d) == FALSE)return FALSE;
00103  if(d.al)type=0;  else type=1;
00104  if(d.sp)split=1; else split=0;
00105  hSave=SetCursor(LoadCursor(NULL,IDC_WAIT));
00106  IntersectObject(type,split);
00107  SetCursor(hSave);
00108  return TRUE;
00109 }
00110 
00111 static short Del_Swap(vector p, long v1l, long v2l, long v3l){
00112  /* test to see if edge common to triangle pair  v1,v2,v3  and v1,v2,p */
00113  /* should be swapped so as to keep the triangles as near equilateral  */
00114  /* as possible.                                                       */
00115  vertex *v1,*v2,*v3;
00116  double cosa,cosb,sina,sinb,sinab;
00117  vector vp3,v13,v23,va,vb,v1p,v2p;
00118  v1=(MainVp+v1l); v2=(MainVp+v2l); v3=(MainVp+v3l);
00119  VECSUB((double)v1->xyz,(double)v3->xyz,v13) O_normalize(v13);
00120  VECSUB((double)v2->xyz,(double)v3->xyz,v23) O_normalize(v23);
00121  VECSUB((double)v1->xyz,p,v1p) O_normalize(v1p);
00122  VECSUB((double)v2->xyz,p,v2p) O_normalize(v2p);
00123  cosa=DOT(v13,v23);
00124  cosb=DOT(v1p,v2p);
00125  if(cosa >= 0.0 && cosb >= 0.0)return 0;     /* a < 90 and b < 90 */
00126  if(cosa <  0.0 && cosb <  0.0)return 1;
00127  CROSS(v13,v23,va) sina=va[0]*va[0]+va[1]*va[1]+va[2]*va[2];
00128  if(sina < 1.e-10)return 0; sina = sqrt(sina);
00129  CROSS(v2p,v1p,vb) sinb=vb[0]*vb[0]+vb[1]*vb[1]+vb[2]*vb[2];
00130  if(sinb < 1.e-10)return 0; sinb = sqrt(sinb);
00131  sinab=sina*cosb+sinb*cosa;
00132  if(sinab < 0.0)return 1;
00133  return 0;
00134 }
00135 
00136 static long BoolAddVertex(vector v, short status){
00137  vertex *vv;
00138  if(!UpdateVertexHeap(Nvert+1)){
00139    MessageBeep(MB_OK);
00140    return Nvert-1;
00141  }
00142  CreateVertex();
00143  vv=(MainVp+Nvert-1);
00144  vv->xyz[0]=(long)v[0];
00145  vv->xyz[1]=(long)v[1];
00146  vv->xyz[2]=(long)v[2];
00147  vv->id=0; vv->status=status;
00148  if(status == DESELECTED){NvertSelect--; NvertDeselect++;}
00149  return Nvert-1;
00150 }
00151 
00152 static workface *add_small_face(long a, long b, long c,
00153                                 long f, long i, workface *w,
00154                                 long *nface){
00155   long nf;
00156   nf = *nface;
00157   if((w=(workface *)X__Realloc(w,(nf+1)*(long)sizeof(workface)))
00158        == NULL)return NULL;
00159   if(!UpdateFaceHeap(Nface+1))return NULL;
00160   CreateFace(a,b,c);
00161   CopyFaceProp((MainFp+f),(MainFp+Nface-1));
00162   w[nf].f=Nface-1;  /* nb:      f = w[i].f */
00163   VECCOPY(w[i].n,w[nf].n)
00164   (*nface)++;
00165   return w;
00166 }
00167 
00168 static long Del_Edgeid(long v1, long v2, workface *w, long k,
00169                        long *fa1, long *fa2, long *e1, long *e2){
00170  face *f;
00171  f=(MainFp+w[k].f);
00172  if((f->V[0] == v1 && f->V[1] == v2) ||
00173     (f->V[0] == v2 && f->V[1] == v1)){
00174    *fa1=w[k].fa[1]; *fa2=w[k].fa[2];
00175    *e1=w[k].ea[1]; *e2=w[k].ea[2];
00176    return f->V[2];
00177  }
00178  else if((f->V[1] == v1 && f->V[2] == v2) ||
00179          (f->V[1] == v2 && f->V[2] == v1)){
00180    *fa1=w[k].fa[2]; *fa2=w[k].fa[0];
00181    *e1=w[k].ea[2]; *e2=w[k].ea[0];
00182    return f->V[0];
00183  }
00184  else if((f->V[2] == v1 && f->V[0] == v2) ||
00185          (f->V[2] == v2 && f->V[0] == v1)){
00186    *fa1=w[k].fa[0]; *fa2=w[k].fa[1];
00187    *e1=w[k].ea[0]; *e2=w[k].ea[1];
00188    return f->V[1];
00189  }
00190  MessageBox(NULL,"Algorithm confused",NULL,MB_OK);
00191  return -1;
00192 }
00193 
00194 static workface *AddDelaunayTriangulation(vector p2, workface *bf1, long bi,
00195                           long nns,long *nf, workface *w,
00196                           long *nwe, workedge **we){
00197  short code,id;
00198  long i,j,k,l,m,t,n,nn,*Dstack=NULL,Dss=0,fa1,fa2;
00199  workedge *wee;
00200  workface *bf;
00201  vector pa,pb,pc;
00202  long vp,w0,w1,w2,vo,vt;
00203  long f1;
00204  long e0,e1,e2,ep;
00205  n= *nf;
00206  /* nns is pointer to original top of work face list before adding new
00207     faces caused by point p2 being inserted in a work face. */
00208  for(i=nns;i<=n;i++){ /* find which face this intersects    */
00209    if(i == n){bf=bf1;   j=bi;} /* use an extra face for the original */
00210    else      {bf=&w[i]; j=i; }
00211    f1=bf->f;
00212    w0=(MainFp+f1)->V[0]; w1=(MainFp+f1)->V[1]; w2=(MainFp+f1)->V[2];
00213    POINT2VECTOR((MainVp+w0)->xyz,pa)
00214    POINT2VECTOR((MainVp+w1)->xyz,pb)
00215    POINT2VECTOR((MainVp+w2)->xyz,pc)
00216    if(EdgePierceFace(p2,pa,pb,pc,&code,&id) && code == 0){
00217      vp=BoolAddVertex(p2,DESELECTED);
00218      if((wee=(workedge *)X__Realloc(*we,(*nwe + 3)*(long)sizeof(workedge)))
00219                == NULL)return NULL;
00220      *we=wee;
00221      if(!UpdateEdgeHeap(Nedge+3))return NULL;
00222      CreateEdge(vp,w0);
00223      e0 = *nwe;     wee[e0].e=Nedge-1; wee[e0].t = -1; wee[e0].b=0;
00224      wee[e0].ea[0] = wee[e0].ea[0] = -1;
00225      CreateEdge(vp,w1);
00226      e1 = *nwe + 1; wee[e1].e=Nedge-1; wee[e1].t = -1; wee[e1].b=0;
00227      wee[e1].ea[0] = wee[e1].ea[1] = -1;
00228      CreateEdge(vp,w2);
00229      e2 = *nwe + 2; wee[e2].e=Nedge-1; wee[e2].t = -1; wee[e2].b=0;
00230      wee[e2].ea[0] = wee[e2].ea[1] = -1;
00231      *nwe = *nwe + 3;
00232      if((w=add_small_face(vp,w0,w1,f1,j,w,nf))==NULL)return NULL;
00233      if((w=add_small_face(vp,w2,w0,f1,j,w,nf))==NULL)return NULL;
00234      (MainFp+f1)->V[0]=vp;       /* modify this face       */
00235      nn = *nf;
00236      w[nn-2].fa[0]=nn-1;         /* adjacency in new faces */
00237      w[nn-2].fa[1]=w[j].fa[0];
00238      w[nn-2].fa[2]=j;
00239      w[nn-1].fa[0]=j;
00240      w[nn-1].fa[1]=w[j].fa[2];
00241      w[nn-1].fa[2]=nn-2;
00242      if((k=w[j].fa[0]) >= 0){   /* change adjacency in adjacent */
00243        for(l=0;l<3;l++)if(w[k].fa[l] == j)w[k].fa[l]=nn-2;
00244      }
00245      if((k=w[j].fa[2]) >= 0){
00246        for(l=0;l<3;l++)if(w[k].fa[l] == j)w[k].fa[l]=nn-1;
00247      }
00248      w[j].fa[0]=nn-2;           /*  change adjacency in this face */
00249      w[j].fa[2]=nn-1;
00250      w[nn-2].ea[0]=e0;
00251      w[nn-2].ea[1]=w[j].ea[0];
00252      w[nn-2].ea[2]=e1;
00253      w[nn-1].ea[0]=e2;
00254      w[nn-1].ea[1]=w[j].ea[2];
00255      w[nn-1].ea[2]=e0;
00256      w[j].ea[0]=e1;
00257      w[j].ea[2]=e2;
00258      if(Dstack == NULL){
00259        if((Dstack=(long *)X__Malloc(sizeof(long)*(3)))
00260                  == NULL)return NULL;
00261      }
00262      else {
00263        if((Dstack=(long *)X__Realloc(Dstack,sizeof(long)*(Dss+3)))
00264                  == NULL)return NULL;
00265      }
00266      if(w[j].fa[1] >= 0)   { Dstack[Dss] = j;    Dss++;}
00267      if(w[nn-2].fa[1] >= 0){ Dstack[Dss] = nn-2; Dss++;}
00268      if(w[nn-1].fa[1] >= 0){ Dstack[Dss] = nn-1; Dss++;}
00269      while(Dss > 0){
00270        Dss--;
00271        j=Dstack[Dss]; k=w[j].fa[1];
00272        if(Dss > 0){
00273          if((Dstack=(long *)X__Realloc(Dstack,sizeof(long)*(Dss))) == NULL){
00274            return NULL;  /* pop off top of stack */
00275          }
00276        }
00277        if((vo=Del_Edgeid((MainFp+(w[j].f))->V[1],
00278                          (MainFp+(w[j].f))->V[2],w,k,
00279                          &fa1,&fa2,&e1,&e2)) < 0)return NULL;
00280        if(Del_Swap(p2,(MainFp+(w[j].f))->V[1],(MainFp+(w[j].f))->V[2],vo)){
00281          e0=w[j].ea[1];
00282          if((m=w[j].fa[2]) >= 0){   /* change adjacency in adjacent */
00283            for(l=0;l<3;l++)if(w[m].fa[l] == j)w[m].fa[l]=k;
00284          }
00285          if(fa1 >= 0){
00286            for(l=0;l<3;l++)if(w[fa1].fa[l] == k)w[fa1].fa[l]=j;
00287          }
00288          (MainEp+wee[e0].e)->V[0]=vp;
00289          (MainEp+wee[e0].e)->V[1]=vo; /* reverse edge */
00290          vt=(MainFp+(w[j].f))->V[2];
00291          (MainFp+(w[j].f))->V[2]=vo;   /* update face j */
00292          w[j].fa[1]=fa1; t=w[j].fa[2]; w[j].fa[2]=k;
00293          w[j].ea[1]=e1; ep=w[j].ea[2]; w[j].ea[2]=e0;
00294          (MainFp+(w[k].f))->V[0]=vp;
00295          (MainFp+(w[k].f))->V[1]=vo;
00296          (MainFp+(w[k].f))->V[2]=vt; /* face k */
00297          w[k].fa[0]=j; w[k].fa[1]=fa2; w[k].fa[2]=t;
00298          w[k].ea[0]=e0; w[k].ea[1]=e2; w[k].ea[2]=ep;
00299          if((Dstack=(long *)X__Realloc(Dstack,sizeof(long)*(Dss+2))) == NULL){
00300            return NULL;  /* push both onto stackstack */
00301          }
00302          if(w[j].fa[1] >= 0){Dstack[Dss] = j; Dss++;}
00303          if(w[k].fa[1] >= 0){Dstack[Dss] = k; Dss++;}
00304        }
00305      }
00306      if(Dstack != NULL)X__Free(Dstack);
00307      return w; /* intersection found */
00308    }
00309  }
00310  return w;
00311 }
00312 
00313 static workface *split_edge(vector p2, long edgeID,
00314                             workface *w, workedge **e,
00315                             long *nface, long *nedge, long *vid){
00316  /* split faces attached to edge edgeID - keep adjacency information */
00317  long nf,i,j,k,l,m,fid,f1id,f2id,faid,e1id,e2id,a0,a1,a2,e0,e1,e2,fai[2],fx;
00318  long s,vp,q1,q2;
00319  face *f;
00320  workedge *be;
00321  long ep;
00322  nf=*nface;
00323  be = *e;
00324  ep=be[edgeID].e;
00325  if(!UpdateVertexHeap(Nvert+1))return NULL;
00326  vp=BoolAddVertex(p2,DESELECTED);
00327  /* identify this new vertex */
00328  (MainVp+vp)->id=(long)(*vid); *vid = (*vid) + 1;
00329  q1=(MainEp+ep)->V[0]; q2=(MainEp+ep)->V[1];
00330  if(!UpdateEdgeHeap(Nedge+1))return NULL;
00331  CreateEdge(vp,(MainEp+ep)->V[1]); (MainEp+ep)->V[1]=vp;
00332  if((be=(workedge *)X__Realloc(be,((*nedge)+1)*(long)sizeof(workedge)))
00333        == NULL)return NULL;
00334  /* new edge is not internal */
00335  be[*nedge].e=Nedge-1; be[*nedge].t=0;  be[*nedge].b=0;
00336  *e=be; e1id = *nedge;
00337  (*nedge)++;
00338  f1id=be[edgeID].ea[0]; f2id=be[edgeID].ea[1];
00339  fid=f1id;
00340  for(i=0;i<2;i++){
00341    if(fid >= 0){
00342      fx=w[fid].f; f=(MainFp+fx);
00343      if     (f->V[0] == q1 && f->V[1] == q2){ s=f->V[2]; k=1; l=0; m=2; }
00344      else if(f->V[0] == q2 && f->V[1] == q1){ s=f->V[2]; k=2; l=0; m=1; }
00345      else if(f->V[1] == q1 && f->V[2] == q2){ s=f->V[0]; k=2; l=1; m=0; }
00346      else if(f->V[1] == q2 && f->V[2] == q1){ s=f->V[0]; k=0; l=1; m=2; }
00347      else if(f->V[2] == q1 && f->V[0] == q2){ s=f->V[1]; k=0; l=2; m=1; }
00348      else if(f->V[2] == q2 && f->V[0] == q1){ s=f->V[1]; k=1; l=2; m=0; }
00349      else return NULL;
00350      a0=w[fid].fa[k]; a1=w[fid].fa[l]; a2=w[fid].fa[m]; /* consistent */
00351      e0=w[fid].ea[k]; e1=w[fid].ea[l]; e2=w[fid].ea[m]; /* numbering  */
00352      f->V[0]=s; f->V[1]=vp; f->V[2]=q1; /* shrink original face */
00353      if(!UpdateEdgeHeap(Nedge+1))return NULL;
00354      CreateEdge(s,vp);         /* offset vertex to vertex at p2 */
00355      if((be=(workedge *)X__Realloc(be,sizeof(workedge)*((*nedge) + 1))) == NULL)
00356         return NULL;
00357      be[*nedge].e=Nedge-1;
00358      be[*nedge].t=1;  /* this is an internal edge in phase 2 */
00359      be[*nedge].b=0; *e=be;
00360      e2id = *nedge;
00361      (*nedge)++;
00362      if((w=add_small_face(s,q2,vp,fx,fid,w,nface)) == NULL)return NULL;
00363      faid = (*nface) - 1;
00364      w[fid].fa[0]=faid; w[fid].fa[1]=a1; w[fid].fa[2]=a2;
00365      w[fid].ea[0]=e2id; w[fid].ea[1]=e1; w[fid].ea[2]=e2;
00366      w[faid].fa[0]=a0; w[faid].fa[1]=a1; w[faid].fa[2]=fid;
00367      w[faid].ea[0]=e0; w[faid].ea[1]=e1id; w[faid].ea[2]=e2id;
00368      if(a0 >= 0)for(j=0;j<3;j++){ /* fix up adjacent face */
00369        if(w[a0].fa[j] == fid)w[a0].fa[j]=faid;
00370      }
00371      be[e2id].ea[0]=fid; be[e2id].ea[1]=faid;
00372      for(j=0;j<2;j++){ /* fix up edge adjacency */
00373        if(be[e0].ea[j] == fid)be[e0].ea[j]=faid;
00374      }
00375      be[e1id].ea[i]=faid;
00376      fai[i]=faid;
00377    }
00378    else be[e1id].ea[i] = -1; /* extra bit of cut edge has no other side */
00379    fid=f2id;
00380  }
00381  if(f1id >= 0 && f2id >= 0){   /* fix adjacent info face in new faces   */
00382    w[fai[0]].fa[1] = fai[1];
00383    w[fai[1]].fa[1] = fai[0];
00384  }
00385  return w;
00386 }
00387 
00388 static void switch_adjacent_faces(long edgeID, workface *w, long nf,
00389                                    workedge *we, long ne){
00390  /* switch diagonal edgeID in two adjacent faces and tidy up */
00391  long i,fid1,fid2,k,l,m;
00392  long a0,a1,a2,e0,e1,e2,b0,b1,b2,d0,d1,d2;
00393  long q1,q2,s1=-1,s2=-1;
00394  face *f1,*f2;
00395  edge *e;
00396  e=(MainEp+we[edgeID].e);
00397  q1=e->V[0]; q2=e->V[1];
00398  fid1=we[edgeID].ea[0]; fid2=we[edgeID].ea[1];
00399  f1=(MainFp+w[fid1].f); f2=(MainFp+w[fid2].f);
00400  if     (f1->V[0] == q1 && f1->V[1] == q2){ s1=f1->V[2]; k=1; l=0; m=2; }
00401  else if(f1->V[0] == q2 && f1->V[1] == q1){ s1=f1->V[2]; k=2; l=0; m=1; }
00402  else if(f1->V[1] == q1 && f1->V[2] == q2){ s1=f1->V[0]; k=2; l=1; m=0; }
00403  else if(f1->V[1] == q2 && f1->V[2] == q1){ s1=f1->V[0]; k=0; l=1; m=2; }
00404  else if(f1->V[2] == q1 && f1->V[0] == q2){ s1=f1->V[1]; k=0; l=2; m=1; }
00405  else if(f1->V[2] == q2 && f1->V[0] == q1){ s1=f1->V[1]; k=1; l=2; m=0; }
00406  /* numbering starts at s1 - clockwise */
00407  a0=w[fid1].fa[k]; a1=w[fid1].fa[l]; a2=w[fid1].fa[m]; /* consistent */
00408  e0=w[fid1].ea[k]; e1=w[fid1].ea[l]; e2=w[fid1].ea[m]; /* numbering  */
00409  if     (f2->V[0] == q1 && f2->V[1] == q2){ s2=f2->V[2]; k=1; l=0; m=2; }
00410  else if(f2->V[0] == q2 && f2->V[1] == q1){ s2=f2->V[2]; k=2; l=0; m=1; }
00411  else if(f2->V[1] == q1 && f2->V[2] == q2){ s2=f2->V[0]; k=2; l=1; m=0; }
00412  else if(f2->V[1] == q2 && f2->V[2] == q1){ s2=f2->V[0]; k=0; l=1; m=2; }
00413  else if(f2->V[2] == q1 && f2->V[0] == q2){ s2=f2->V[1]; k=0; l=2; m=1; }
00414  else if(f2->V[2] == q2 && f2->V[0] == q1){ s2=f2->V[1]; k=1; l=2; m=0; }
00415  /* for second face opposite winding */
00416  b0=w[fid2].fa[m]; b1=w[fid2].fa[l]; b2=w[fid2].fa[k]; /* consistent */
00417  d0=w[fid2].ea[m]; d1=w[fid2].ea[l]; d2=w[fid2].ea[k]; /* numbering  */
00418  if(s1 < 0 || s2 < 0){
00419    MessageBeep(MB_OK);
00420    return;
00421  }
00422  e->V[0]=s1; e->V[1]=s2;     /* opposite edge same face adjacency    */
00423  f1->V[0]=s1; f1->V[1]=s2; f1->V[2]=q1;
00424  w[fid1].fa[0]=fid2; w[fid1].fa[1]=b0; w[fid1].fa[2]=a2;
00425  w[fid1].ea[0]=edgeID; w[fid1].ea[1]=d0; w[fid1].ea[2]=e2;
00426  f2->V[0]=s1; f2->V[1]=q2; f2->V[2]=s2;
00427  w[fid2].fa[0]=a0; w[fid2].fa[1]=b2; w[fid2].fa[2]=fid1;
00428  w[fid2].ea[0]=e0; w[fid2].ea[1]=d2; w[fid2].ea[2]=edgeID;
00429  /* reset adjacency information in adjacent faces - a0 and b0 */
00430  if(a0 >= 0)for(i=0;i<3;i++){
00431    if(w[a0].fa[i] == fid1)w[a0].fa[i]=fid2;
00432  }
00433  if(b0 >= 0)for(i=0;i<3;i++){
00434    if(w[b0].fa[i] == fid2)w[b0].fa[i]=fid1;
00435  }
00436  /* and for edge e0 and d0 */
00437  for(i=0;i<2;i++){
00438    if(we[e0].ea[i] == fid1)we[e0].ea[i]=fid2;
00439    if(we[d0].ea[i] == fid2)we[d0].ea[i]=fid1;
00440  }
00441 }
00442 
00443 static int can_switch_faces(long edgeID, workface *w, workedge *we){
00444  /* test to see if faces adjacent to edge edgeID can be swapped    */
00445  /* they can be swapped if edge "edgeID" would remain internal to  */
00446  /* both faces after any swappping takes place - use vector cross  */
00447  /* product for edges adjacent to q1 and q2 (not e) and test that  */
00448  /* crosses point in same direction ie. c1 dot c2 > 0. Note all    */
00449  /* vectors lie in the same plane as they originated in the same   */
00450  /* original triangular face.                                      */
00451  long fid1,fid2;
00452  long q1,q2,s1=-1,s2=-1;
00453  face *f1,*f2;
00454  edge *e;
00455  vector vs1q1,vs2q1,vs1q2,vs2q2,va,vb;
00456  e=(MainEp+we[edgeID].e);
00457  q1=e->V[0]; q2=e->V[1];
00458  fid1=we[edgeID].ea[0]; fid2=we[edgeID].ea[1];
00459  f1=(MainFp+w[fid1].f); f2=(MainFp+w[fid2].f);
00460  if     (f1->V[0] == q1 && f1->V[1] == q2)s1=f1->V[2];
00461  else if(f1->V[0] == q2 && f1->V[1] == q1)s1=f1->V[2];
00462  else if(f1->V[1] == q1 && f1->V[2] == q2)s1=f1->V[0];
00463  else if(f1->V[1] == q2 && f1->V[2] == q1)s1=f1->V[0];
00464  else if(f1->V[2] == q1 && f1->V[0] == q2)s1=f1->V[1];
00465  else if(f1->V[2] == q2 && f1->V[0] == q1)s1=f1->V[1];
00466  if     (f2->V[0] == q1 && f2->V[1] == q2)s2=f2->V[2];
00467  else if(f2->V[0] == q2 && f2->V[1] == q1)s2=f2->V[2];
00468  else if(f2->V[1] == q1 && f2->V[2] == q2)s2=f2->V[0];
00469  else if(f2->V[1] == q2 && f2->V[2] == q1)s2=f2->V[0];
00470  else if(f2->V[2] == q1 && f2->V[0] == q2)s2=f2->V[1];
00471  else if(f2->V[2] == q2 && f2->V[0] == q1)s2=f2->V[1];
00472  if(s1 < 0 || s2 < 0){
00473    MessageBeep(MB_OK);
00474    return 0; /* should never happen */
00475  }
00476  VECSUB((double)(MainVp+s1)->xyz,(double)(MainVp+q1)->xyz,vs1q1)
00477         O_normalize(vs1q1);
00478  VECSUB((double)(MainVp+s2)->xyz,(double)(MainVp+q1)->xyz,vs2q1)
00479         O_normalize(vs2q1);
00480  VECSUB((double)(MainVp+s1)->xyz,(double)(MainVp+q2)->xyz,vs1q2)
00481         O_normalize(vs1q2);
00482  VECSUB((double)(MainVp+s2)->xyz,(double)(MainVp+q2)->xyz,vs2q2)
00483         O_normalize(vs2q2);
00484  CROSS(vs2q1,vs1q1,va)
00485  CROSS(vs1q2,vs2q2,vb)
00486  if(DOT(va,vb) > 0.0)return 1; /* OK  */
00487  return 0;                     /* Bad */
00488 }
00489 
00490 static int lastID,NF,NE;
00491 static workface *WF;
00492 static workedge *WE;
00493 
00494 static void SetConnectingID(long id){
00495  long eid;
00496  WF[id].id=lastID;
00497  if(WF[id].ea[0] >= 0 && WE[WF[id].ea[0]].b == 0 &&
00498    WF[id].fa[0] >= 0 && WF[WF[id].fa[0]].id < 0)
00499    SetConnectingID(WF[id].fa[0]);
00500  if(WF[id].ea[1] >= 0 && WE[WF[id].ea[1]].b == 0 &&
00501    WF[id].fa[1] >= 0 && WF[WF[id].fa[1]].id < 0)
00502    SetConnectingID(WF[id].fa[1]);
00503  if(WF[id].ea[2] >= 0 && WE[WF[id].ea[2]].b == 0 &&
00504    WF[id].fa[2] >= 0 && WF[WF[id].fa[2]].id < 0)
00505    SetConnectingID(WF[id].fa[2]);
00506 }
00507 
00508 static void FindBitsAndPieces(workface *wf, long nf,
00509                              workedge *we, long ne, long pid){
00510  face *f;
00511  edge *e;
00512  vertex *vp,*Vp,*v0,*v1,*v2;
00513  long LastVp;
00514  long c,i,id,nvs,k,inc,Nvert1,Nface1,Nedge1;
00515  char str[16],pass1[]="Work",pass2[]="Tool";
00516  double x,y,z;
00517  lastID=0;
00518  NF=nf; NE=ne;
00519  WF=wf; WE=we;
00520  for(i=0;i<nf;i++)wf[i].id = -1;
00521  while(1){ /* keep going until all the bits have been processed */
00522    for(id=0;id<nf;id++){
00523      if(wf[id].id == -1)goto PROCESSIT;
00524    }
00525    break;      /* no bits have been found - so breakout */
00526    PROCESSIT:
00527    SetConnectingID(id);
00528    lastID++;
00529  }
00530  /* now split up the bits and pieces by copying and deleting old workpiece */
00531  if(lastID < 1)return; /* no bits found so don't do any cutting */
00532 #if 0
00533 for(i=0;i<nf;i++){
00534 f=(MainFp+wf[i].f);
00535 if     (wf[i].id == 0){ f->color[0]=255; f->color[1]=  0; f->color[2]=  0;}
00536 else if(wf[i].id == 1){ f->color[0]=  0; f->color[1]=255; f->color[2]=  0;}
00537 else if(wf[i].id == 2){ f->color[0]=  0; f->color[1]=  0; f->color[2]=255;}
00538 else if(wf[i].id == 3){ f->color[0]=255; f->color[1]=255; f->color[2]=  0;}
00539 else if(wf[i].id == 4){ f->color[0]=  0; f->color[1]=255; f->color[2]=255;}
00540 else if(wf[i].id == 5){ f->color[0]=255; f->color[1]=  0; f->color[2]=255;}
00541 }
00542 return;
00543 #endif
00544  LastVp=Nvert;
00545  for(id=0;id<lastID;id++){
00546    vp=MainVp; for(c=0;c<Nvert;c++){vp->id=0; vp++;}/* flag */
00547    for(i=0;i<nf;i++){ /* flag all vertices for faces in bit "id" */
00548      if(wf[i].id == id){ /* this bit */
00549        f=(MainFp+wf[i].f);
00550        (MainVp+(f->V[0]))->id=1;
00551        (MainVp+(f->V[1]))->id=1;
00552        (MainVp+(f->V[2]))->id=1;
00553      }
00554    }
00555    x=y=z=0.0;
00556    /* assign copy IDs to vertices and count */
00557    nvs=0; vp=MainVp; for(c=0;c<Nvert;c++){
00558      if(vp->id == 1){
00559        x += (double)vp->xyz[0];
00560        y += (double)vp->xyz[1];
00561        z += (double)vp->xyz[2];
00562        nvs++;
00563      }
00564      vp++;
00565    }
00566    CreateSkeleton(FirstSp); /* For each "bit" create a Skeleton node */
00567    ZeroSkeletonBoundingBox(MainSp);
00568    if(pid == 1)sprintf(str,"%s-%ld",pass1,id+1);
00569    else        sprintf(str,"%s-%ld",pass2,id+1);
00570    MainSp->xyz[0]=(long)(x/(double)nvs);
00571    MainSp->xyz[1]=(long)(y/(double)nvs);
00572    MainSp->xyz[2]=(long)(z/(double)nvs);
00573    strcpy(MainSp->name,str);
00574    for(Nedge1=0,i=0;i<ne;i++){ /* count edges and faces */
00575      inc=0;
00576      if((k=we[i].ea[0]) >= 0 && wf[k].id == id)inc=1;
00577      if((k=we[i].ea[1]) >= 0 && wf[k].id == id)inc=1;
00578      if(inc == 1)Nedge1++;
00579    }
00580    for(Nface1=0,i=0;i<nf;i++){if(wf[i].id == id)Nface1++;}
00581    if(nvs > 0 && Nedge1 > 0 && Nface1 > 0 &&
00582       UpdateVertexHeap(Nvert+nvs)  &&  /* make space */
00583       UpdateEdgeHeap(Nedge+Nedge1) &&
00584       UpdateFaceHeap(Nface+Nface1)){
00585      Nvert1=Nvert; nvs=0; vp=MainVp; for(c=0;c<Nvert1;c++){
00586        if(vp->id == 1){
00587          CreateVertex();
00588          Vp=(MainVp+Nvert-1);
00589          Vp->sp=MainSp;
00590          VECCOPY(vp->xyz,Vp->xyz)
00591          vp->id=(long)Nvert-1;
00592          Vp->status=DESELECTED;
00593          NvertSelect--; NvertDeselect++;
00594          nvs++;
00595        }
00596        else vp->id = -1;
00597        vp++;
00598      }
00599      for(i=0;i<nf;i++){ /* duplicate faces             */
00600        if(wf[i].id == id){ /* face is part of this bit */
00601          f=(MainFp+wf[i].f);
00602          v0=(MainVp+(f->V[0])); v1=(MainVp+(f->V[1])); v2=(MainVp+(f->V[2]));
00603          CreateFace(v0->id,v1->id,v2->id);
00604          CopyFaceProp(f,(MainFp+Nface-1));
00605        }
00606      }
00607      for(i=0;i<ne;i++){ /* duplicate edges */
00608        inc=0;
00609        if((k=we[i].ea[0]) >= 0 && wf[k].id == id)inc=1;
00610        if((k=we[i].ea[1]) >= 0 && wf[k].id == id)inc=1;
00611        if(inc == 1){ /* this is an edge in this part */
00612          e=(MainEp+we[i].e);
00613          v0=(MainVp+(e->V[0])); v1=(MainVp+(e->V[1]));
00614          CreateEdge(v0->id,v1->id);
00615        }
00616      }
00617    }
00618  }
00619  vp=MainVp; for(c=0;c<LastVp;c++){ /* flag vertices for deletion */
00620    if(vp->status == SELECTED){
00621      vp->status=INEDITOR; NvertSelect--; NvertDeselect++;
00622 
00623    }
00624    else if(vp->status == DESELECTED){
00625      vp->status=SELECTED; NvertSelect++; NvertDeselect--;
00626    }
00627    vp++;
00628  }
00629  EraseVertex(1);
00630  vp=MainVp; for(c=0;c<Nvert;c++){
00631    if(vp->status == INEDITOR){
00632      vp->status=SELECTED; NvertSelect++; NvertDeselect--;
00633    }
00634    vp++;
00635  }
00636  return;
00637 }
00638 
00639 static int FindAdjFaces(workface *wf, long nf, workedge *we, long ne){
00640  edge *e;
00641  face *f;
00642  vertex *vp;
00643  vtxadj *vl=NULL;
00644  long c,nvl=0;
00645  long *fl,i,j,k,id,id0,id1,id2,fjd,fkd,n,m,kk,nl[3],ml[3];
00646  vp=MainVp; for(c=0;c<Nvert;c++){
00647    if(vp->status == DESELECTED){ /* work vertex */
00648      vp->id=nvl;
00649      nvl++;
00650    }
00651    else vp->id = -10; /* just for fun */
00652    vp++;
00653  }
00654  if((vl=(vtxadj *)X__Malloc(nvl*sizeof(vtxadj))) == NULL)return 0;
00655  for(i=0;i<nvl;i++){
00656    vl[i].nf=0; vl[i].ne=0;
00657    vl[i].flist=NULL; vl[i].elist=NULL;
00658  }
00659  for(i=0;i<nf;i++){ /* make list of work faces attached to each vertex */
00660    f=(MainFp+wf[i].f);
00661    for(j=0;j<3;j++){
00662      id=(MainVp+(f->V[j]))->id;
00663      fl=vl[id].flist;
00664      n=vl[id].nf;
00665      if(fl == NULL){
00666        if((fl=(long *)X__Malloc(sizeof(long))) == NULL)return 0;
00667      }
00668      else{
00669        if((fl=(long *)X__Realloc(fl,(n+1)*sizeof(long))) == NULL)return 0;
00670      }
00671      fl[n]=i;
00672      vl[id].flist=fl;
00673      vl[id].nf=n+1;
00674    }
00675  }
00676  for(i=0;i<nf;i++){ /* find faces that are adjacent to face i */
00677    f=(MainFp+wf[i].f);
00678    id0=(MainVp+(f->V[0]))->id;
00679    id1=(MainVp+(f->V[1]))->id;
00680    id2=(MainVp+(f->V[2]))->id;
00681    nl[0]=id0; ml[0]=id1;
00682    nl[1]=id1; ml[1]=id2;
00683    nl[2]=id2; ml[2]=id0;
00684    for(kk=0;kk<3;kk++){
00685      wf[i].fa[kk] = -1;
00686      if((n=vl[nl[kk]].nf) > 0 && (m=vl[ml[kk]].nf) > 0){
00687        for(j=0;j<n;j++){
00688          fjd=vl[nl[kk]].flist[j];
00689          for(k=0;k<m;k++){
00690            fkd=vl[ml[kk]].flist[k];
00691            if(fkd == fjd && fkd != i){
00692              wf[i].fa[kk]=fkd;
00693              goto ENDF;
00694            }
00695          }
00696        }
00697      }
00698      ENDF:;
00699    }
00700  }
00701  for(i=0;i<ne;i++){ /* find faces that are adjacent to edge i */
00702    e=(MainEp+we[i].e);
00703    id0=(MainVp+(e->V[0]))->id; id1=(MainVp+(e->V[1]))->id;
00704    kk=0; we[i].ea[0] = we[i].ea[1] = -1;
00705    if((n=vl[id0].nf) > 0 && (m=vl[id1].nf) > 0){
00706      for(j=0;j<n;j++){
00707        fjd=vl[id0].flist[j];
00708        for(k=0;k<m;k++){
00709          fkd=vl[id1].flist[k];
00710          if(fkd == fjd){
00711            we[i].ea[kk]=fkd;
00712            kk++;
00713            if(kk == 2)goto ENDEE;  /* terminate when we have two */
00714          }
00715        }
00716      }
00717      ENDEE:;
00718    }
00719  }
00720  for(i=0;i<ne;i++){ /* make list of work edges attached to each vertex */
00721    e=(MainEp+we[i].e);
00722    for(j=0;j<2;j++){
00723      id=(MainVp+(e->V[j]))->id;
00724      fl=vl[id].elist;
00725      n=vl[id].ne;
00726      if(fl == NULL){
00727        if((fl=(long *)X__Malloc(sizeof(long))) == NULL)return 0;
00728      }
00729      else {
00730        if((fl=(long *)X__Realloc(fl,(n+1)*sizeof(long))) == NULL)return 0;
00731      }
00732      fl[n]=i;
00733      vl[id].elist=fl;
00734      vl[id].ne=n+1;
00735    }
00736  }
00737  for(i=0;i<nf;i++){ /* find edges that are adjacent to face i */
00738    f=(MainFp+wf[i].f);
00739    id0=(MainVp+(f->V[0]))->id;
00740    id1=(MainVp+(f->V[1]))->id;
00741    id2=(MainVp+(f->V[2]))->id;
00742    nl[0]=id0; ml[0]=id1;
00743    nl[1]=id1; ml[1]=id2;
00744    nl[2]=id2; ml[2]=id0;
00745    for(kk=0;kk<3;kk++){
00746      wf[i].ea[kk] = -1;
00747      if((n=vl[nl[kk]].ne) > 0 && (m=vl[ml[kk]].ne) > 0){
00748        for(j=0;j<n;j++){
00749          fjd=vl[nl[kk]].elist[j];
00750          for(k=0;k<m;k++){
00751            fkd=vl[ml[kk]].elist[k];
00752            if(fkd == fjd){
00753              wf[i].ea[kk]=fkd;
00754              goto ENDE;
00755            }
00756          }
00757        }
00758      }
00759      ENDE:;
00760    }
00761  }
00762  for(i=0;i<nvl;i++){
00763    if(vl[i].flist != NULL)X__Free(vl[i].flist);
00764    if(vl[i].elist != NULL)X__Free(vl[i].elist);
00765  }
00766  X__Free(vl);
00767  return nvl;
00768 }
00769 
00770 static void IntersectObject(int work_only, int split){
00771  /* workface is the face being worked on */
00772  /* tool face is the face doing the cutting */
00773  workedge *we,*wee;
00774  tooledge *te,*xe;
00775  workface *w;
00776  toolface *t,*x;
00777  face *ff1;
00778  long f1;
00779  vertex *vpp,*v0,*v1,*v2;
00780  long vp,w0,w1,w2;
00781  edge *ep;
00782  short xn;
00783  long e0,e1,e2;
00784  long c,i,j,k,l,nwf,nns,passID,LastVtxID,StartVertex;
00785  vector du,dv,n,pa,pb,pc,p0,p1,p2;
00786  long n_tool_face=0,n_work_face=0,n_tool_edge=0,n_work_edge=0,
00787       x_tool_face=0,x_tool_edge=0,n_hidden_face=0,n_bad_face=0;
00788  unsigned char key,ekey,first_time=1;
00789  if(NvertSelect == 0 || NvertDeselect == 0)return;
00790  if(NvertSelect > 32000)return;
00791  if((ff1=MainFp) == NULL)return;
00792  StartVertex=Nvert;
00793 //debug=fopen("D:debug","w");
00794  vpp=MainVp; for(i=0;i<Nvert;i++){
00795    vpp->id=0; vpp++;
00796  }
00797  t=NULL; w=NULL; te=NULL; we=NULL; x=NULL; xe=NULL;
00798  for(c=0;c<Nface;c++){ /* find number of work and tool faces */
00799    v0=(MainVp+ff1->V[0]); v1=(MainVp+ff1->V[1]); v2=(MainVp+ff1->V[2]);
00800    if(v0->status == SELECTED &&
00801       v1->status == SELECTED &&
00802       v2->status == SELECTED)n_tool_face++;
00803    else if(v0->status == DESELECTED &&
00804            v1->status == DESELECTED &&
00805            v2->status == DESELECTED)n_work_face++;
00806    else if(v0->status == HIDDEN &&
00807            v1->status == HIDDEN &&
00808            v2->status == HIDDEN)n_hidden_face++;
00809    else  n_bad_face++;
00810    ff1++;
00811  }
00812  if(n_bad_face > 0){
00813    char str[256];
00814    LoadString(hThisInstance,IDX_MESSAGE1,str,255);
00815    MessageBox(NULL,str,NULL,MB_OK);
00816    return;
00817  }
00818  if((t=(toolface *)X__Malloc(n_tool_face*(long)sizeof(toolface)))
00819        == NULL)goto BERR;
00820  if((w=(workface *)X__Malloc(n_work_face*(long)sizeof(workface)))
00821        == NULL)goto BERR;
00822  x_tool_face=n_work_face;
00823  if((x=(toolface *)X__Malloc(x_tool_face*(long)sizeof(toolface)))
00824        == NULL)goto BERR;
00825  n_work_face=0; n_tool_face=0; x_tool_face=0;
00826  for(ff1=MainFp,c=0;c<Nface;c++){
00827   v0=(MainVp+ff1->V[0]); v1=(MainVp+ff1->V[1]); v2=(MainVp+ff1->V[2]);
00828   POINT2VECTOR(v0->xyz,p0)
00829   POINT2VECTOR(v1->xyz,p1)
00830   POINT2VECTOR(v2->xyz,p2)
00831   VECSUB(p1,p0,dv)
00832   VECSUB(p2,p0,du)
00833   if(v0->status == SELECTED &&
00834      v1->status == SELECTED &&
00835      v2->status == SELECTED){
00836     CROSS(dv,du,n)
00837     if(O_normalize(n) == FAIL){
00838       VECSUB(p0,p1,dv)
00839       VECSUB(p2,p1,du)
00840       CROSS(dv,du,n)
00841       if(O_normalize(n) == FAIL){
00842         VECSUB(p0,p2,dv)
00843         VECSUB(p1,p2,du)
00844         CROSS(dv,du,n)
00845         if(O_normalize(n) == FAIL)goto BERR2;
00846       }
00847     }
00848     t[n_tool_face].f=c;
00849     VECCOPY(v0->xyz,t[n_tool_face].p0)  /* note VECCOPY is a macro */
00850     VECCOPY(v1->xyz,t[n_tool_face].p1)  /* OK for POINTS as well   */
00851     VECCOPY(v2->xyz,t[n_tool_face].p2)
00852     VECCOPY(n,t[n_tool_face].n)
00853     n_tool_face++;
00854   }
00855   else if(v0->status == DESELECTED &&
00856           v1->status == DESELECTED &&
00857           v2->status == DESELECTED){
00858    w[n_work_face].f=c;
00859     for(i=0;i<3;i++){
00860       w[n_work_face].fa[i] = -1;
00861       w[n_work_face].ea[i] = -1;
00862     }
00863     CROSS(dv,du,n)
00864     if(O_normalize(n) == FAIL){
00865       VECSUB(p0,p1,dv)
00866       VECSUB(p2,p1,du)
00867       CROSS(dv,du,n)
00868       if(O_normalize(n) == FAIL){
00869         VECSUB(p0,p2,dv)
00870         VECSUB(p1,p2,du)
00871         CROSS(dv,du,n)
00872         if(O_normalize(n) == FAIL)goto BERR2;
00873       }
00874     }
00875     VECCOPY(n,w[n_work_face].n)
00876     VECCOPY(v0->xyz,x[x_tool_face].p0)  /* make copy for use by when */
00877     VECCOPY(v1->xyz,x[x_tool_face].p1)  /* this becomes the tool     */
00878     VECCOPY(v2->xyz,x[x_tool_face].p2)
00879     VECCOPY(n,x[x_tool_face].n)
00880     x[x_tool_face].f=c;  /* this is not really needed */
00881     x_tool_face++;
00882     n_work_face++;
00883   }
00884   ff1++;
00885  }
00886  for(ep=MainEp,c=0;c<Nedge;c++){
00887    v0=(MainVp+ep->V[0]); v1=(MainVp+ep->V[1]);
00888    if(v0->status == SELECTED && v1->status == SELECTED)n_tool_edge++;
00889    else if(v0->status == DESELECTED && v1->status == DESELECTED){
00890      n_work_edge++;
00891      x_tool_edge++;
00892    }
00893    ep++;
00894  }
00895  if((te=(tooledge *)X__Malloc(n_tool_edge*(long)sizeof(tooledge)))
00896       == NULL)goto BERR;
00897  if((we=(workedge *)X__Malloc(n_work_edge*(long)sizeof(workedge)))
00898       == NULL)goto BERR;
00899  if((xe=(tooledge *)X__Malloc(x_tool_edge*(long)sizeof(tooledge)))
00900       == NULL)goto BERR;
00901  n_tool_edge=0; n_work_edge=0; x_tool_edge=0;
00902  for(ep=MainEp,c=0;c<Nedge;c++){ /* get all tool edges */
00903    v0=(MainVp+ep->V[0]); v1=(MainVp+ep->V[1]);
00904    if(v0->status == SELECTED && v1->status == SELECTED){
00905      POINT2VECTOR(v0->xyz,te[n_tool_edge].p0)
00906      POINT2VECTOR(v1->xyz,te[n_tool_edge].p1)
00907      te[n_tool_edge].e=c;
00908      n_tool_edge++;
00909    }
00910    else if(v0->status == DESELECTED && v1->status == DESELECTED){
00911      we[n_work_edge].e=c;    /* get all the workface edges - these      */
00912      we[n_work_edge].t=0;    /* are the original workface edges, pass 1 */
00913      we[n_work_edge].b=0;    /* will add lots of new edges              */
00914      we[n_work_edge].ea[0] = we[n_work_edge].ea[1] = -1;
00915      n_work_edge++;
00916      POINT2VECTOR(v0->xyz,xe[x_tool_edge].p0) /* make copy of work  */
00917      POINT2VECTOR(v1->xyz,xe[x_tool_edge].p1) /* edges for use when */
00918      xe[x_tool_edge].e=c;                     /* this becomes tool  */
00919      x_tool_edge++;
00920    }
00921    ep++;
00922  }
00923  if(n_work_face == 0 || n_tool_face == 0)goto QUIT;
00924  passID=1;
00925  SECONDCUT:
00926  nwf=n_work_face;
00927  for(i=0;i<nwf;i++){ /* make intersection in work face due to tool */
00928    f1=w[i].f;
00929    w0=(MainFp+f1)->V[0]; w1=(MainFp+f1)->V[1]; w2=(MainFp+f1)->V[2];
00930    POINT2VECTOR((MainVp+w0)->xyz,pa)
00931    POINT2VECTOR((MainVp+w1)->xyz,pb)
00932    POINT2VECTOR((MainVp+w2)->xyz,pc)
00933    nns=n_work_face;
00934    /* find tool edges that intersects workface i (any of the original wfs) */
00935    for(j=0;j<n_tool_edge;j++){
00936      if(EdgeThroughFace(pa,pb,pc,w[i].n,te[j].p0,te[j].p1,p2,0)){
00937        if(nns == n_work_face){ /* first subdivision  1->3 faces */
00938          vp=BoolAddVertex(p2,DESELECTED);
00939          if((wee=(workedge *)X__Realloc(we,(n_work_edge+3)*(long)sizeof(workedge)))
00940                == NULL)goto BERR;
00941          we=wee;
00942          if(!UpdateEdgeHeap(Nedge+3))goto BERR;
00943          CreateEdge(vp,w0);  /* id this edge as a phase 1 added edge */
00944          e0=n_work_edge;   we[e0].e=Nedge-1;  we[e0].t = -1;  we[e0].b=0;
00945          we[e0].ea[0] = we[e0].ea[1] = -1;
00946          CreateEdge(vp,w1);
00947          e1=n_work_edge+1; we[e1].e=Nedge-1;  we[e1].t = -1;  we[e1].b=0;
00948          we[e1].ea[0] = we[e1].ea[1] = -1;
00949          CreateEdge(vp,w2);
00950          e2=n_work_edge+2; we[e2].e=Nedge-1;  we[e2].t = -1;  we[e2].b=0;
00951          we[e2].ea[0] = we[e2].ea[1] = -1;
00952          n_work_edge+=3;
00953          if((w=add_small_face(vp,w0,w1,f1,i,w,&n_work_face))==NULL)goto BERR;
00954          if((w=add_small_face(vp,w2,w0,f1,i,w,&n_work_face))==NULL)goto BERR;
00955          (MainFp+f1)->V[0]=vp;   /* modify this face                   */
00956          /* fix up adjacency info */
00957          w[n_work_face - 2].fa[0]=n_work_face-1;
00958          w[n_work_face - 2].fa[1]=w[i].fa[0];
00959          w[n_work_face - 2].fa[2]=i;
00960          w[n_work_face - 1].fa[0]=i;
00961          w[n_work_face - 1].fa[1]=w[i].fa[2];
00962          w[n_work_face - 1].fa[2]=n_work_face-2;
00963          if((k=w[i].fa[0]) >= 0){   /* change adjacency in adjacent */
00964            for(l=0;l<3;l++)if(w[k].fa[l] == j)w[k].fa[l]=n_work_face-2;
00965          }
00966          if((k=w[i].fa[2]) >= 0){
00967            for(l=0;l<3;l++)if(w[k].fa[l] == j)w[k].fa[l]=n_work_face-1;
00968          }
00969          w[i].fa[0]=n_work_face-2;
00970          w[i].fa[2]=n_work_face-1;
00971          w[n_work_face - 2].ea[0]=e0;
00972          w[n_work_face - 2].ea[1]=w[i].ea[0];
00973          w[n_work_face - 2].ea[2]=e1;
00974          w[n_work_face - 1].ea[0]=e2;
00975          w[n_work_face - 1].ea[1]=w[i].ea[2];
00976          w[n_work_face - 1].ea[2]=e0;
00977          w[i].ea[0]=e1;
00978          w[i].ea[2]=e2;
00979        }
00980        else{
00981          /* add vertext at p2 in wf(i) or any of it's subdivisions -
00982             then go on to optimize the triangulation of any faces internal
00983             to original wf(i) */
00984          if((w=AddDelaunayTriangulation(p2,&w[i],i,nns,&n_work_face,w,
00985                 &n_work_edge,&we)) == NULL)goto BERR;
00986        }
00987      }
00988    }
00989    if(GetAsyncKeyState(VK_ESCAPE) & 0x8000){
00990      MessageBeep(MB_OK);
00991      goto QUIT;
00992    }
00993  }
00994  LastVtxID=FindAdjFaces(w,n_work_face,we,n_work_edge);
00995  /* iterative procedure for more optimal triangulation */
00996  for(i=0;i<n_tool_face;i++){ /* check original workface edge into tool */
00997    POINT2VECTOR(t[i].p0,pa)
00998    POINT2VECTOR(t[i].p1,pb)
00999    POINT2VECTOR(t[i].p2,pc)
01000    VECCOPY(t[i].n,n)
01001    nns=n_work_edge;
01002    for(j=0;j<nns;j++){
01003      if(we[j].t != 0)continue;  /* only original workface edges */
01004      ep=(MainEp+we[j].e);
01005      POINT2VECTOR((MainVp+(ep->V[0]))->xyz,p0)
01006      POINT2VECTOR((MainVp+(ep->V[1]))->xyz,p1)
01007      if((xn=EdgeThroughFace(pa,pb,pc,n,p0,p1,p2,2)) == 1){
01008        if((w=split_edge(p2,j,w,&we,&n_work_face,&n_work_edge,&LastVtxID))
01009              == NULL || we == NULL)goto BERR;
01010      }
01011      else if(xn == 2){ /* this is a boundary edge */
01012        we[j].b=1;
01013      }
01014    }
01015    if(GetAsyncKeyState(VK_ESCAPE) & 0x8000){
01016      MessageBeep(MB_OK);
01017      goto QUIT;
01018    }
01019  }
01020  for(i=0;i<n_tool_face;i++){ /* check workface edge into tool */
01021    POINT2VECTOR(t[i].p0,pa)
01022    POINT2VECTOR(t[i].p1,pb)
01023    POINT2VECTOR(t[i].p2,pc)
01024    VECCOPY(t[i].n,n)
01025    ITERATE: nns=0;
01026    for(j=0;j<n_work_edge;j++){  /* no more edges required  */
01027      if(we[j].t == 0)continue;  /* skip any original edges */
01028      if(we[j].b)continue;       /* ship boundary edges     */
01029      ep=(MainEp+we[j].e);
01030      POINT2VECTOR((MainVp+(ep->V[0]))->xyz,p0)
01031      POINT2VECTOR((MainVp+(ep->V[1]))->xyz,p1)
01032      if((xn=EdgeThroughFace(pa,pb,pc,n,p0,p1,p2,2)) == 1){
01033        if(can_switch_faces(j,w,we)){
01034          switch_adjacent_faces(j,w,n_work_face,we,n_work_edge);
01035          POINT2VECTOR((MainVp+(ep->V[0]))->xyz,p0)
01036          POINT2VECTOR((MainVp+(ep->V[1]))->xyz,p1)
01037          if(EdgeThroughFace(pa,pb,pc,n,p0,p1,p2,2) == 2){
01038            we[j].b=1; /* swapped edge is boundary */
01039          }
01040        }
01041        else{
01042          nns=1; /* raise flag => can't swap - try again later */
01043        }
01044      }
01045      else if(xn == 2){ /* this is a boundary edge */
01046        we[j].b=1;
01047      }
01048    }
01049    if(GetAsyncKeyState(VK_ESCAPE) & 0x8000){
01050      MessageBeep(MB_OK);
01051      goto QUIT;
01052    }
01053    if(nns)goto ITERATE;
01054  }
01055  if(split)FindBitsAndPieces(w,n_work_face,we,n_work_edge,passID);
01056  if(first_time && (! work_only)){ /* swap the tool and workface - use old workface as tool */
01057    first_time=0;
01058    X__Free(we); we=NULL; n_work_edge=0;
01059    n_work_edge=n_tool_edge;  /* make new work edges from the tool edges */
01060    if((we=(workedge *)X__Malloc(n_work_edge*(long)sizeof(workedge)))
01061            == NULL)goto BERR;
01062    for(i=0;i<n_tool_edge;i++){
01063        we[i].e=te[i].e;
01064        we[i].t=0; we[i].b=0;
01065        we[i].ea[0] = we[i].ea[1] = -1;
01066    }
01067    X__Free(te); te=xe;xe=NULL; n_tool_edge=x_tool_edge; /* new tool edges */
01068    X__Free(w); w=NULL; n_work_face=0;
01069    n_work_face=n_tool_face;
01070    if((w=(workface *)X__Malloc(n_work_face*(long)sizeof(workface)))
01071           == NULL)goto BERR;
01072    for(i=0;i<n_tool_face;i++){ /* make new work faces from the tool faces */
01073      w[i].f=t[i].f;
01074      for(j=0;j<3;j++){
01075        w[i].fa[j] = -1;
01076        w[i].ea[j] = -1;
01077      }
01078      VECCOPY(t[i].n,w[i].n)
01079    }
01080    X__Free(t);  t=x;  x=NULL;  n_tool_face=x_tool_face; /* new tool faces */
01081    vpp=MainVp; for(c=0;c<Nvert;c++){
01082      if(vpp->status == SELECTED){
01083        vpp->status=DESELECTED; NvertSelect--; NvertDeselect++;
01084      }
01085      else if(vpp->status == DESELECTED){
01086        vpp->status=SELECTED; NvertSelect++; NvertDeselect--;
01087      }
01088      vpp++;
01089    }
01090    passID=2;
01091    goto SECONDCUT;
01092  }
01093  goto QUIT;
01094  BERR2:
01095  MessageBox(NULL,"Normal - Problem",NULL,MB_OK); goto QUIT;
01096  BERR:
01097  MessageBox(NULL,"Memory Error",NULL,MB_OK);
01098  QUIT:
01099  if(t != NULL)X__Free(t);
01100  if(w != NULL)X__Free(w);
01101  if(te != NULL)X__Free(te);
01102  if(we != NULL)X__Free(we);
01103  if(x != NULL)X__Free(x);
01104  if(xe != NULL)X__Free(xe);
01105 //fclose(debug);
01106  return;
01107 }
01108 

Generated on Sun Apr 27 14:20:10 2014 for OpenFX by  doxygen 1.5.6