DECIMATE.CPP

Go to the documentation of this file.
00001 /* --
00002 OpenFX - Modelling, Animation and Rendering Package
00003 Copyright (C) OpenFX Development Team
00004 -- */
00005 
00006 /*  DECIMATE.CPP  */
00007 
00008 #include "vtk.hh"
00009 #include <stdlib.h>
00010 #include <stdio.h>
00011 #include <math.h>
00012 #include <windows.h>
00013 
00014 #define UNIT         32768L
00015 #define DESELECTED       0
00016 #define SELECTED         1
00017 #define INEDITOR         6
00018 
00019 #ifdef __cplusplus
00020 extern "C" {
00021 #endif
00022 
00023 #include "struct.h"
00024 #include "dstruct.h"
00025 
00026 #ifdef __cplusplus
00027 }
00028 #endif
00029 
00030 #include "decimate.h"
00031 
00032 static long ColourToLong(unsigned char *c);
00033 
00034 static void LongToColour(long id, unsigned char *c);
00035 
00036 class SfxReader : public vtkPolySource
00037 {
00038 public:
00039   SfxReader();
00040   ~SfxReader();
00041   char *GetClassName() {return "SfxReader";};
00042   int GetNumberOfVertices(void);
00043   int GetNumberOfEdge(void);
00044   int GetNumberOfFaces(void);
00045 
00046 protected:
00047   void Execute();
00048   int  Nv,Nf,Ne;
00049 };
00050 
00051 class SfxBaseWriter : public vtkObject
00052 {
00053 public:
00054   SfxBaseWriter();
00055   virtual void Write();
00056   void Update();
00057 
00058 protected:
00059   vtkDataSet *Input;
00060   virtual void WriteData() = 0;
00061 };
00062 
00063 class SfxWriter : public SfxBaseWriter
00064 {
00065 public:
00066   SfxWriter();
00067   ~SfxWriter();
00068   char *GetClassName() {return "SfxWriter";};
00069   void SetInput(vtkPolyData *input);
00070   void SetInput(vtkPolyData &input) {this->SetInput(&input);};
00071   vtkPolyData *GetInput() {return (vtkPolyData *)this->Input;};
00072   int GetNumberOfVertices(void);
00073   int GetNumberOfEdge(void);
00074   int GetNumberOfFaces(void);
00075   void EraseOldStructure(long );
00076   void OffsetStructure(long , long , long , long );
00077 
00078 protected:
00079   int Nv,Ne,Nf;
00080   void WriteData();
00081   void InsertInVertexList(long , long , long );
00082   void BuildEdges(long );
00083 };
00084 
00085 static HWND      hParent;
00086 static HINSTANCE hThisInstance;
00087 
00088 static BOOL CALLBACK SimplifyDlgProc(HWND hwnd, UINT msg,
00089                              WPARAM wparam, LPARAM lparam);
00090 
00091 #if __WATCOMC__
00092 int APIENTRY LibMain(HANDLE hDLL, DWORD dwReason, LPVOID lpReserved){
00093 #else
00094 BOOL WINAPI DllMain(HANDLE hDLL, DWORD dwReason, LPVOID lpReserved){
00095 #endif
00096   switch (dwReason) {
00097     case DLL_PROCESS_ATTACH: {
00098       hThisInstance=(HINSTANCE)hDLL;
00099       if(hDLL == NULL)MessageBeep(MB_OK);
00100       break;
00101     }
00102     case DLL_PROCESS_DETACH:
00103       break;
00104   }
00105   return TRUE;
00106 }
00107 
00108 
00109 extern "C" BOOL _Xmodeler
00110  (HWND parent_window,HWND info_window,X__STRUCTURE *lpevi){
00111  HCURSOR hSave;
00112  static struct bp {
00113    double TargetReduction;
00114    long   MaximumIterations,MaximumSubIterations;
00115    double InitialError,ErrorIncrement,
00116           AspectRatio,InitialFeatureAngle;
00117  } d;
00118  lpEVI=lpevi;
00119  hParent=parent_window;
00120  d.TargetReduction=0.9;
00121  d.MaximumIterations=10;
00122  d.MaximumSubIterations=2;
00123  d.InitialError=0.0000;
00124  d.ErrorIncrement=0.002;  //  0.0002
00125  d.AspectRatio=20.0;
00126  d.InitialFeatureAngle=60.0;
00127  if(DialogBoxParam(hThisInstance,MAKEINTRESOURCE(DLG_SIM),hParent,
00128              (DLGPROC)SimplifyDlgProc,(LPARAM)&d) == FALSE)return FALSE;
00129  hSave=SetCursor(LoadCursor(NULL,IDC_WAIT));
00130  {
00131   char message[256];
00132   int Nv1,Nf1,Nv2,Nf2;
00133   SfxReader sfxinput;
00134   SfxWriter sfxoutput;
00135   vtkDecimate deci;
00136   sfxinput.Update();
00137   Nv1=sfxinput.GetNumberOfVertices();
00138   Nf1=sfxinput.GetNumberOfFaces();
00139   deci.SetInput(sfxinput.GetOutput());
00140   deci.SetTargetReduction((float)d.TargetReduction);
00141   deci.SetMaximumIterations(d.MaximumIterations);
00142   deci.SetMaximumSubIterations(d.MaximumSubIterations);
00143   deci.SetInitialError((float)d.InitialError);
00144   deci.SetErrorIncrement((float)d.ErrorIncrement);
00145   deci.SetAspectRatio((float)d.AspectRatio);
00146   deci.SetInitialFeatureAngle((float)d.InitialFeatureAngle);
00147   sfxoutput.SetInput(deci.GetOutput());
00148   sfxoutput.Write();
00149   Nv2=sfxoutput.GetNumberOfVertices();
00150   Nf2=sfxoutput.GetNumberOfFaces();
00151   sprintf(message,"Decimated %ld Vertices %ld Faces\n to %ld Vertices %ld Faces",
00152           Nv1,Nf1,Nv2,Nf2);
00153   MessageBox(parent_window,message,"Decimate",MB_OK);
00154  }
00155  SetCursor(hSave);
00156  return TRUE;
00157 }
00158 
00159 static BOOL CALLBACK SimplifyDlgProc(HWND hwnd, UINT msg,
00160                              WPARAM wparam, LPARAM lparam){
00161  BOOL err;
00162  double f;
00163  int i;
00164  static struct bp {
00165    double TargetReduction;
00166    long   MaximumIterations,MaximumSubIterations;
00167    double InitialError,ErrorIncrement,
00168           AspectRatio,InitialFeatureAngle;
00169  } *dp;
00170  char str[32];
00171  switch( msg ) {
00172    case WM_INITDIALOG:
00173      dp=(struct bp *)lparam;
00174      SetDlgItemInt(hwnd,DLG_SIM_MAXIMUMITERATIONS,dp->MaximumIterations,FALSE);
00175      SetDlgItemInt(hwnd,DLG_SIM_MAXIMUMSUBITERATIONS,dp->MaximumSubIterations,FALSE);
00176      sprintf(str,"%.1lf",dp->TargetReduction*100.0);
00177      SetDlgItemText(hwnd,DLG_SIM_TARGETREDUCTION,(LPCTSTR)str);
00178      sprintf(str,"%.4lf",dp->InitialError);
00179      SetDlgItemText(hwnd,DLG_SIM_INITIALERROR,(LPCTSTR)str);
00180      sprintf(str,"%.4lf",dp->ErrorIncrement);
00181      SetDlgItemText(hwnd,DLG_SIM_ERRORINCREMENT,(LPCTSTR)str);
00182      sprintf(str,"%.2lf",dp->AspectRatio);
00183      SetDlgItemText(hwnd,DLG_SIM_ASPECTRATIO,(LPCTSTR)str);
00184      sprintf(str,"%.2lf",dp->InitialFeatureAngle);
00185      SetDlgItemText(hwnd,DLG_SIM_INITIALFEATUREANGLE,(LPCTSTR)str);
00186      CentreDlgOnS(hwnd);
00187      return (TRUE);
00188    case WM_COMMAND:
00189       switch(LOWORD(wparam)){
00190         case IDCANCEL:
00191           EndDialog(hwnd,FALSE);
00192           return(TRUE);
00193         case IDOK:
00194           if(GetDlgItemText(hwnd,DLG_SIM_TARGETREDUCTION,str,10) == 0){
00195             EndDialog(hwnd,FALSE); return TRUE;
00196           }
00197           dp->TargetReduction=atof(str)/100.0;
00198           if(GetDlgItemText(hwnd,DLG_SIM_INITIALERROR,str,10) == 0){
00199             EndDialog(hwnd,FALSE); return TRUE;
00200           }
00201           dp->InitialError=atof(str);
00202           if(GetDlgItemText(hwnd,DLG_SIM_ERRORINCREMENT,str,10) == 0){
00203             EndDialog(hwnd,FALSE); return TRUE;
00204           }
00205           dp->ErrorIncrement=atof(str);
00206           if(GetDlgItemText(hwnd,DLG_SIM_ASPECTRATIO,str,10) == 0){
00207             EndDialog(hwnd,FALSE); return TRUE;
00208           }
00209           dp->AspectRatio=atof(str);
00210           if(GetDlgItemText(hwnd,DLG_SIM_INITIALFEATUREANGLE,str,10) == 0){
00211             EndDialog(hwnd,FALSE); return TRUE;
00212           }
00213           dp->InitialFeatureAngle=atof(str);
00214           i=GetDlgItemInt(hwnd,DLG_SIM_MAXIMUMITERATIONS,&err,FALSE);
00215           if(err)dp->MaximumIterations=i;
00216           i=GetDlgItemInt(hwnd,DLG_SIM_MAXIMUMSUBITERATIONS,&err,FALSE);
00217           if(err)dp->MaximumSubIterations=i;
00218           EndDialog(hwnd,TRUE);
00219           return(TRUE);
00220         default:
00221           break;
00222       }
00223       break;
00224     default: break;
00225  }
00226  return(FALSE);
00227 }
00228 
00229 long ColourToLong(unsigned char *c){
00230  return ((long)(c[0]) << 16) | ((long)(c[1]) << 8) | ((long)c[2]);
00231 }
00232 
00233 void LongToColour(long id, unsigned char *c){
00234  c[0] = (unsigned char)((id >> 16) & 0xff);
00235  c[1] = (unsigned char)((id >>  8) & 0xff);
00236  c[2] = (unsigned char)((id      ) & 0xff);
00237 }
00238 
00239 SfxReader::SfxReader()
00240 {
00241  Nv=Ne=Nf=0;
00242 }
00243 
00244 SfxReader::~SfxReader()
00245 {
00246 }
00247 
00248 int SfxReader::GetNumberOfVertices(void){return (int)this->Nv;}
00249 int SfxReader::GetNumberOfEdge(void){return (int)this->Ne;}
00250 int SfxReader::GetNumberOfFaces(void){return (int)this->Nf;}
00251 
00252 void SfxReader::Execute()
00253 {
00254   face *fp;
00255   float x[3];
00256   int i,pts[3],count;
00257   vtkFloatPoints *newPoints;
00258   vtkCellArray *newTris;
00259   vtkPolyData *output = this->GetOutput();
00260   vtkUserDefined *vdata;
00261   if(NvertSelect == 0)return;
00262   newPoints = new vtkFloatPoints(NvertSelect);
00263   vdata     = new vtkUserDefined(NvertSelect);
00264   // make a best guess for vertex color based on one of the faces
00265   // attached to that vertex
00266   for(i=0,count=0;i<Nface;i++){
00267     fp=(MainFp+i);
00268     if((MainVp+fp->V[0])->status == SELECTED &&
00269        (MainVp+fp->V[1])->status == SELECTED &&
00270        (MainVp+fp->V[2])->status == SELECTED){
00271       (MainVp+fp->V[0])->id=ColourToLong(fp->color);
00272       (MainVp+fp->V[1])->id=ColourToLong(fp->color);
00273       (MainVp+fp->V[2])->id=ColourToLong(fp->color);
00274     }
00275   }
00276   for(count=0,i=0;i<Nvert;i++){
00277     if((MainVp+i)->status == SELECTED){
00278       x[0] = (float)((MainVp+i)->xyz[0])/((float)UNIT);
00279       x[1] = (float)((MainVp+i)->xyz[1])/((float)UNIT);
00280       x[2] = (float)((MainVp+i)->xyz[2])/((float)UNIT);
00281       // store the best guess at vertex colour
00282       vdata->InsertNextUserDefined((void *)((MainVp+i)->id));
00283       (MainVp+i)->id=count++;
00284       newPoints->InsertNextPoint(x);
00285       this->Nv++;
00286     }
00287   }
00288   for(i=0,count=0;i<Nface;i++){
00289     fp=(MainFp+i);
00290     if((MainVp+fp->V[0])->status == SELECTED &&
00291        (MainVp+fp->V[1])->status == SELECTED &&
00292        (MainVp+fp->V[2])->status == SELECTED)count++;
00293   }
00294   newTris = new vtkCellArray;
00295   newTris->Allocate(count);
00296   for(i=0;i<Nface;i++){
00297     fp=(MainFp+i);
00298     if((MainVp+fp->V[0])->status == SELECTED &&
00299        (MainVp+fp->V[1])->status == SELECTED &&
00300        (MainVp+fp->V[2])->status == SELECTED){
00301       pts[0] = (int)((MainVp+fp->V[0])->id);
00302       pts[1] = (int)((MainVp+fp->V[1])->id);
00303       pts[2] = (int)((MainVp+fp->V[2])->id);
00304       newTris->InsertNextCell(3,pts);
00305       this->Nf++;
00306     }
00307   }
00308   output->SetPoints(newPoints);
00309   newPoints->Delete();
00310   output->SetPolys(newTris);
00311   newTris->Delete();
00312   output->GetPointData()->SetUserDefined(vdata);
00313   vdata->Delete();
00314   output->Squeeze();
00315 }
00316 
00317 SfxBaseWriter::SfxBaseWriter()
00318 {
00319   this->Input = NULL;
00320 }
00321 
00322 void SfxBaseWriter::Write()
00323 {
00324   if ( !this->Input ) {
00325     return;
00326   }
00327   this->Input->Update();
00328   this->WriteData();
00329   this->Input->ReleaseData();
00330 }
00331 
00332 void SfxBaseWriter::Update()
00333 {
00334   this->Write();
00335 }
00336 
00337 SfxWriter::SfxWriter()
00338 {
00339  Nv=0; Ne=0; Nf=0;
00340 }
00341 
00342 SfxWriter::~SfxWriter()
00343 {
00344 }
00345 
00346 int SfxWriter::GetNumberOfVertices(void){return (int)this->Nv;}
00347 int SfxWriter::GetNumberOfEdge(void){return (int)this->Ne;}
00348 int SfxWriter::GetNumberOfFaces(void){return (int)this->Nf;}
00349 
00350 void SfxWriter::SetInput(vtkPolyData *input)
00351 {
00352   if ( this->Input != input )
00353     {
00354     this->Input = (vtkDataSet *) input;
00355     this->Modified();
00356     }
00357 }
00358 
00359 void SfxWriter::WriteData()
00360 {
00361   vtkPoints *pts;
00362   vtkCellArray *polys;
00363   vtkPolyData *input=(vtkPolyData *)this->Input;
00364 
00365   if ( (pts = input->GetPoints()) == NULL ||
00366   (polys = input->GetPolys()) == NULL ){
00367     return;
00368   }
00369   vertex *Vp;
00370   face   *Fp;
00371   float p[3];
00372   int i,npts,npolys;
00373   long BaseVert;
00374   BaseVert=Nvert;
00375   npts=input->GetNumberOfPoints();
00376   npolys=input->GetNumberOfPolys();
00377   this->Nv=npts;
00378   this->Nf=npolys;
00379   if(npts > 0){
00380     if(!UpdateVertexHeap(Nvert+npts))return;
00381     for(i=0;i<npts;i++){
00382       pts->GetPoint(i,p);
00383       CreateVertex();
00384       Vp=(MainVp+Nvert-1);
00385       Vp->id=0;
00386       Vp->sp=NULL;
00387       Vp->xyz[0]=(long)(p[0]*(float)UNIT);
00388       Vp->xyz[1]=(long)(p[1]*(float)UNIT);
00389       Vp->xyz[2]=(long)(p[2]*(float)UNIT);
00390     }
00391   }
00392   if(npolys > 0){
00393     int *indx;
00394     if(!UpdateFaceHeap(Nface+npolys))return;
00395     vtkPointData *pd=input->GetPointData();
00396     vtkUserDefined *data=pd->GetUserDefined();
00397     int ns=data->GetNumberOfUserDefined();
00398     for (polys->InitTraversal(); polys->GetNextCell(npts,indx); ){
00399       CreateFace(BaseVert+(long)indx[0],
00400                  BaseVert+(long)indx[1],
00401                  BaseVert+(long)indx[2]);
00402       // get the user defined for the vertex that remains after
00403       // decimations
00404       long c = (long)data->GetUserDefined(indx[0]);
00405       // set the face based on the data from one of its vertices
00406       unsigned char fc[3];
00407       LongToColour(c,fc);
00408       for(i=0;i<3;i++)(MainFp+Nface-1)->color[i]=fc[i];
00409 //RSFx may need to be changed to account for new face structure
00410       this->InsertInVertexList(BaseVert,indx[0],indx[1]);
00411       this->InsertInVertexList(BaseVert,indx[1],indx[2]);
00412       this->InsertInVertexList(BaseVert,indx[2],indx[0]);
00413     }
00414     this->BuildEdges(BaseVert);
00415   }
00416 
00417 
00418   this->EraseOldStructure(BaseVert);
00419 }
00420 
00421 // Use the vertex's skeleton pointer and integer identifer as temporary
00422 // storage for build edge adjacency lists since they are not uses on new
00423 // vertices.
00424 //
00425 void SfxWriter::InsertInVertexList(long base, long Vj, long Vi){
00426  vertex *vj,*vi;
00427  long *list,i,j;
00428  vj=(MainVp+base+Vj);
00429  vi=(MainVp+base+Vi);
00430  list = (long *)vi->sp;
00431  if(vi->id > 0)for(i=0;i<vi->id;i++)if(list[i] == Vj)return;
00432  list = (long *)vj->sp;
00433  if(vj->id > 0)for(j=0;j<vj->id;j++)if(list[j] == Vi)return;
00434  if(vi->id == 0){
00435    if((list = (long *)X__Malloc((vi->id + 1)*sizeof(long))) == NULL){
00436      return;
00437    }
00438    vi->sp=(struct Designer_SKELETON_tag *)list;
00439  }
00440  else{
00441    list = (long *)vi->sp;
00442    if((list = (long *)X__Realloc(list,(vi->id + 1)*sizeof(long))) == NULL){
00443      return;
00444    }
00445    vi->sp=(struct Designer_SKELETON_tag *)list;
00446  }
00447  list[vi->id] = base+Vj;
00448  (vi->id)++;
00449 }
00450 
00451 void SfxWriter::BuildEdges(long base){
00452  long n,j,i,*list;
00453  vertex *vp;
00454  vp=(MainVp+base);
00455  for(j=base;j<Nvert;j++){
00456    if(vp->id != 0 && vp->sp != NULL){
00457      if(!UpdateEdgeHeap(Nedge+vp->id))return;
00458      list = (long *)vp->sp;
00459      for(i=0;i<vp->id;i++)CreateEdge(j,list[i]);
00460      X__Free(vp->sp); vp->sp=NULL; vp->id=0;
00461    }
00462    vp++;
00463  }
00464 }
00465 
00466 void SfxWriter::EraseOldStructure(long base){
00467  long c;
00468  vertex *vp;
00469  vp=(MainVp+base); for(c=base;c<Nvert;c++){
00470    if(vp->status == SELECTED){
00471      vp->status=INEDITOR; NvertSelect--; NvertDeselect++;
00472    }
00473    vp++;
00474  }
00475  EraseVertex(1);
00476  vp=MainVp; for(c=0;c<Nvert;c++){
00477    if(vp->status == INEDITOR){
00478      vp->status=SELECTED; NvertSelect++; NvertDeselect--;
00479    }
00480    vp++;
00481  }
00482 }
00483 
00484 void SfxWriter::OffsetStructure(long base, long dx, long dy, long dz){
00485  long c;
00486  vertex *vp;
00487  vp=(MainVp+base); for(c=base;c<Nvert;c++){
00488    vp->xyz[0] += dx;
00489    vp->xyz[1] += dy;
00490    vp->xyz[2] += dz;
00491    vp++;
00492  }
00493 }

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