Main Page | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members

vtkCatmullClarkFilter.cpp

Go to the documentation of this file.
00001 /*=========================================================================
00002 
00003   Program:   Visualization Toolkit
00004   Module:    $RCSfile: vtkCatmullClarkFilter.cxx,v $
00005   Language:  C++
00006   Date:      $Date: 2001/11/13 14:13:55 $
00007   Version:   $Revision: 1.11 $
00008   Thanks:    This work was supported bt PHS Research Grant No. 1 P41 RR13218-01
00009              from the National Center for Research Resources
00010 
00011 Copyright (c) 1993-2001 Leopold Kühschelm, Daniel Wagner, Sebastian Zambal
00012 All rights reserved.
00013 
00014 Redistribution and use in source and binary forms, with or without
00015 modification, are permitted provided that the following conditions are met:
00016 
00017  * Redistributions of source code must retain the above copyright notice,
00018    this list of conditions and the following disclaimer.
00019 
00020  * Redistributions in binary form must reproduce the above copyright notice,
00021    this list of conditions and the following disclaimer in the documentation
00022    and/or other materials provided with the distribution.
00023 
00024  * Neither name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names
00025    of any contributors may be used to endorse or promote products derived
00026    from this software without specific prior written permission.
00027 
00028  * Modified source versions must be plainly marked as such, and must not be
00029    misrepresented as being the original software.
00030 
00031 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
00032 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00033 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00034 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
00035 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00036 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00037 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00038 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00039 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00040 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00041 
00042 =========================================================================*/
00043 #include "vtkCatmullClarkFilter.h"
00044 #include "vtkEdgeTable.h"
00045 #include "vtkObjectFactory.h"
00046 #include "vtkFloatArray.h"
00047 #include "vtkGenericCell.h"
00048 
00049 vtkCatmullClarkFilter* vtkCatmullClarkFilter::New()
00050 {
00051   // First try to create the object from the vtkObjectFactory
00052   vtkObject* ret = vtkObjectFactory::CreateInstance("vtkCatmullClarkFilter");
00053   if(ret)
00054     {
00055     return (vtkCatmullClarkFilter*)ret;
00056     }
00057   // If the factory was unable to create the object, then create it here.
00058   return new vtkCatmullClarkFilter;
00059 }
00060 
00061 void vtkCatmullClarkFilter::insertEdgePoint(CellData &cell, EdgePoint *newElement) {
00062     newElement->next = cell.edgePoints;
00063     cell.edgePoints = newElement;
00064 }
00065 
00066 EdgePoint *vtkCatmullClarkFilter::findEdgePoint(CellData &cell, vtkIdType id1, vtkIdType id2) {
00067     EdgePoint *result = cell.edgePoints;
00068     bool found = false;
00069     while((result != NULL) && (found == false)) {
00070         if (((result->p1 == id1) && (result->p2 == id2)) ||
00071             ((result->p1 == id2) && (result->p2 == id1))) {     // found edge
00072             found = true;
00073         } else {
00074             result = result->next;
00075         }
00076     }
00077     return result;
00078 }
00079 
00080 void vtkCatmullClarkFilter::insertVertexPoint(CellData &cell, VertexPoint *newElement) {
00081     newElement->next = cell.vertexPoints;
00082     cell.vertexPoints = newElement;
00083 }
00084 
00085 VertexPoint *vtkCatmullClarkFilter::findVertexPoint(CellData &cell, vtkIdType id) {
00086     VertexPoint *result = cell.vertexPoints;
00087     bool found = false;
00088     while((result != NULL) && (found == false)) {
00089         if (result->v_old == id) {     // found vertex
00090             found = true;
00091         } else {
00092             result = result->next;
00093         }
00094     }
00095     return result;
00096 }
00097 
00098 void vtkCatmullClarkFilter::computeFacePoint(vtkCell *cell, float *facePoint) {
00099     facePoint[0] = 0.0f;
00100     facePoint[1] = 0.0f;
00101     facePoint[2] = 0.0f;
00102     vtkPoints *points = cell->GetPoints();
00103     int cpoints = cell->GetNumberOfPoints();
00104     for (int i = 0; i < cpoints; ++i) {
00105         float *current = points->GetPoint(i);
00106         facePoint[0] += (current[0] / cpoints);
00107         facePoint[1] += (current[1] / cpoints);
00108         facePoint[2] += (current[2] / cpoints);
00109     }
00110 }
00111 
00112 vtkIdList *vtkCatmullClarkFilter::getNeighborIds(vtkPolyData *input, vtkIdType i) {
00113     vtkIdList *neighbors = vtkIdList::New();
00114 
00115     vtkIdList *neighborCells = vtkIdList::New();
00116     input->GetPointCells(i, neighborCells);
00117     for (int j = 0; j < neighborCells->GetNumberOfIds(); ++j) {
00118 
00119         vtkIdList *cellPoints = vtkIdList::New();
00120         input->GetCellPoints(neighborCells->GetId(j), cellPoints);
00121         int cpoints = cellPoints->GetNumberOfIds();
00122         for (int k = 0; k < cpoints; ++k) {
00123 
00124             vtkIdType ptId1 = cellPoints->GetId(k);
00125             vtkIdType ptId2 = cellPoints->GetId((k+1) % cpoints);
00126 
00127             if (i == ptId1) {
00128                 if (neighbors->IsId(ptId2) < 0) {
00129                     neighbors->InsertNextId(ptId2);
00130                 }
00131             }
00132             if (i == ptId2) {
00133                 if (neighbors->IsId(ptId1) < 0) {
00134                     neighbors->InsertNextId(ptId1);
00135                 }
00136             }
00137         }
00138     }
00139     return neighbors;
00140 }
00141 
00142 void vtkCatmullClarkFilter::Subdivision(vtkPolyData *input, vtkPolyData *output) {
00143     // BuildLinks(), generate topological information
00144     input->BuildLinks();
00145 
00146     // create the building blocks of the output-polydata.
00147     vtkPoints    *outputPoints = vtkPoints::New();
00148     vtkCellArray *outputPolys  = vtkCellArray::New();
00149 
00150     // create the array holding the information about face-, edge- and
00151     // vertex-points
00152     CellData *cells = new CellData[input->GetNumberOfCells()];
00153     for (int i = 0; i < input->GetNumberOfCells(); ++i) {
00154         cells[i].edgePoints   = NULL;
00155         cells[i].vertexPoints = NULL;
00156     }
00157     int countInputCells = input->GetNumberOfCells();
00158 
00159     // for each cell...
00160     for (int i = 0; i < countInputCells;  i++) {
00161 
00162         // get the current cell
00163         vtkGenericCell *cell = vtkGenericCell::New();
00164         input->GetCell(i, cell);
00165 
00166         // get the number of points in the current cell
00167         int cpoints = cell->GetNumberOfPoints();
00168 
00169         //=============================================
00170         // Compute the face point and add it to the
00171         // output-points
00172         //=============================================
00173         float *facePoint = new float[3];
00174         computeFacePoint(cell, facePoint);
00175         cells[i].facePoint = outputPoints->InsertNextPoint(facePoint);
00176 
00177         //=============================================
00178         // Compute the edge points
00179         //=============================================
00180         for (int j = 0; j < cpoints; ++j) {
00181 
00182             // determine ids of the two vertices that form the edge
00183             vtkIdType id1 = cell->GetPointId(j);
00184             vtkIdType id2 = cell->GetPointId((j+1) % cpoints);
00185 
00186             // check: has the neighbouring cell already computed the edge-point?
00187             vtkIdList *neighborList = vtkIdList::New();
00188             input->GetCellEdgeNeighbors(i, id1, id2, neighborList);
00189             EdgePoint *edgePoint = NULL;
00190             vtkIdType neighbor = 0;
00191             if (neighborList->GetNumberOfIds() > 0) {
00192                 neighbor = neighborList->GetId(0);      // assume, there is only one neighbor
00193                 edgePoint = findEdgePoint(cells[neighbor], id1, id2);
00194             }
00195 
00196             if (edgePoint == NULL) {         // edge not found at neighbor; has to be computed
00197 
00198                 // compute the face-point of the neighbor
00199                 float *facePoint_n = new float[3];
00200                 computeFacePoint(input->GetCell(neighbor), facePoint_n);
00201 
00202                 float *edgePoint = new float[3];
00203                 edgePoint[0] = ((input->GetPoint(id1))[0] + 
00204                             (input->GetPoint(id2))[0] +
00205                             (outputPoints->GetPoint(cells[i].facePoint))[0] +
00206                             facePoint_n[0]) / 4.0f;
00207                 edgePoint[1] = ((input->GetPoint(id1))[1] +
00208                             (input->GetPoint(id2))[1] +
00209                             (outputPoints->GetPoint(cells[i].facePoint))[1] +
00210                             facePoint_n[1]) / 4.0f;
00211                 edgePoint[2] = ((input->GetPoint(id1))[2] +
00212                             (input->GetPoint(id2))[2] +
00213                             (outputPoints->GetPoint(cells[i].facePoint))[2] +
00214                             facePoint_n[2]) / 4.0f;
00215 
00216                 EdgePoint *newEdgePoint = new EdgePoint;
00217                 newEdgePoint->p1 = id1;
00218                 newEdgePoint->p2 = id2;
00219                 newEdgePoint->e = outputPoints->InsertNextPoint(edgePoint);
00220                 insertEdgePoint(cells[i], newEdgePoint);
00221 
00222             } else {                         // edge found at neighbor; insert given information
00223 
00224                 EdgePoint *newEdgePoint = new EdgePoint;
00225                 newEdgePoint->p1 = id1;
00226                 newEdgePoint->p2 = id2;
00227                 newEdgePoint->e = edgePoint->e;
00228                 insertEdgePoint(cells[i], newEdgePoint);
00229             }
00230         }
00231 
00232         //=============================================
00233         // Compute the vertex points
00234         //=============================================
00235         for (int j = 0; j < cpoints; ++j) {
00236 
00237             // get the global id of the point
00238             vtkIdType id = cell->GetPointId(j);
00239 
00240             // check: has the neighboring cell already computed the vertex-point?
00241             vtkIdList *neighborCells = vtkIdList::New();
00242             input->GetPointCells(id, neighborCells);
00243 
00244             VertexPoint *vertexPoint = NULL;
00245             int k = 0;
00246 
00247             while ((vertexPoint == NULL) && 
00248                    (k < neighborCells->GetNumberOfIds())) {
00249                 vertexPoint = findVertexPoint(cells[neighborCells->GetId(k)], id);
00250                 ++k;
00251             }
00252             if (vertexPoint == NULL) {          // vertex point must be computed
00253 
00254                 float *coord = new float[3];
00255                 coord[0] = 0.0f;
00256                 coord[1] = 0.0f;
00257                 coord[2] = 0.0f;
00258 
00259                 // find out the neighbors
00260                 vtkIdList *neighbors = getNeighborIds(input, id);
00261 
00262                 int n = neighbors->GetNumberOfIds();
00263 
00264                 vtkIdList *neighborCells = vtkIdList::New();
00265                 input->GetPointCells(id, neighborCells);
00266                 int a = neighborCells->GetNumberOfIds();
00267 
00268                 float weight_v = ((float)n-2.0f)/(float)n;
00269                 float weight_e = 1.0f/(float)(n*n);
00270                 float weight_f = 1.0f/(float)(n*n);
00271 
00272                 float *sum = new float[3];
00273                 sum[0] = 0.0f;
00274                 sum[1] = 0.0f;
00275                 sum[2] = 0.0f;
00276 
00277                 // add weighted sum of involved face-points
00278                 float *fp = new float[3];
00279                 for (int l = 0; l < a; ++l) {
00280                     computeFacePoint(input->GetCell(neighborCells->GetId(l)), fp);
00281                     sum[0] += fp[0];
00282                     sum[1] += fp[1];
00283                     sum[2] += fp[2];
00284                 }
00285                 delete fp;
00286 
00287                 // add weighted sum of involved edge-points
00288                 for (int l = 0; l < n; ++l) {
00289                     sum[0] += input->GetPoint(neighbors->GetId(l))[0];
00290                     sum[1] += input->GetPoint(neighbors->GetId(l))[1];
00291                     sum[2] += input->GetPoint(neighbors->GetId(l))[2];
00292                 }
00293 
00294                 // add weighted vertex
00295                 coord[0] = (input->GetPoint(id))[0] * weight_v + sum[0]*weight_e;
00296                 coord[1] = (input->GetPoint(id))[1] * weight_v + sum[1]*weight_e;
00297                 coord[2] = (input->GetPoint(id))[2] * weight_v + sum[2]*weight_e;
00298 
00299 /*
00300                 coord[0] = (input->GetPoint(id))[0];
00301                 coord[1] = (input->GetPoint(id))[1];
00302                 coord[2] = (input->GetPoint(id))[2];
00303 */
00304 
00305                 VertexPoint *newVertexPoint = new VertexPoint;
00306                 newVertexPoint->v_old = id;
00307                 newVertexPoint->v = outputPoints->InsertNextPoint(coord);
00308                 insertVertexPoint(cells[i], newVertexPoint);
00309             } else {
00310                 VertexPoint *newVertexPoint = new VertexPoint;
00311                 newVertexPoint->v_old = id;
00312                 newVertexPoint->v = vertexPoint->v;
00313                 insertVertexPoint(cells[i], newVertexPoint);
00314             }
00315         }
00316 
00317         //=============================================
00318         // Create new Cell
00319         //=============================================
00320         for (int j = 0; j < cpoints; ++j) {
00321             vtkIdList *newPointIds = vtkIdList::New();
00322             vtkIdType id1 = cell->GetPointId((vtkIdType) j);
00323             vtkIdType id2 = cell->GetPointId((vtkIdType) ((j+1) % cpoints));
00324             vtkIdType id3 = cell->GetPointId((vtkIdType) ((j+2) % cpoints));
00325             vtkIdType e1  = (findEdgePoint(cells[i], id1, id2))->e;
00326             vtkIdType e2  = (findEdgePoint(cells[i], id2, id3))->e;
00327             vtkIdType v   = (findVertexPoint(cells[i], id2))->v;
00328             vtkIdType f   = cells[i].facePoint;
00329             newPointIds->InsertNextId(v);
00330             newPointIds->InsertNextId(e1);
00331             newPointIds->InsertNextId(f);
00332             newPointIds->InsertNextId(e2);
00333             outputPolys->InsertNextCell(newPointIds);
00334         }
00335 
00336         EdgePoint *ep = cells[i].edgePoints;
00337         while (ep != NULL) {
00338             ep = ep->next;
00339         }
00340 
00341         VertexPoint *vp = cells[i].vertexPoints;
00342         while (vp != NULL) {
00343             vp = vp->next;
00344         }
00345     }
00346 
00347     // We now assign the points and polys to the output-vtkPolyData.
00348     output->SetPoints(outputPoints);
00349     output->SetPolys(outputPolys);
00350 
00351     // free memory 
00352     // ToDo: remove linked lists and other stuff
00353     delete [] cells;
00354     outputPoints->Delete();
00355     outputPolys->Delete();
00356 }
00357 
00358 void vtkCatmullClarkFilter::Execute(void) {
00359 
00360     vtkPolyData *input;
00361     vtkPolyData *output; 
00362     vtkPolyData *intermediate;
00363 
00364     int subdivisions = GetNumberOfSubdivisions();
00365 
00366     if (subdivisions == 0) {
00367         // No subdivision
00368     } else if (subdivisions == 1) {
00369         input = GetInput();
00370         output = GetOutput();
00371         Subdivision(input, output);
00372     } else for(int i = 0; i < subdivisions; ++i) {
00373         if (i == 0) {
00374             input = GetInput();
00375             intermediate = vtkPolyData::New();
00376             Subdivision(input, intermediate);
00377         } else if (i < subdivisions-1) {
00378             input->Delete();
00379             input = intermediate;
00380             intermediate = vtkPolyData::New();
00381             Subdivision(input, intermediate);
00382         } else {
00383             input->Delete();
00384             input = intermediate;
00385             output = GetOutput();
00386             Subdivision(intermediate, output);
00387         }
00388     }
00389 }
00390 
00391 
00392 void vtkCatmullClarkFilter::GenerateSubdivisionPoints (vtkPolyData *inputDS,vtkIntArray *edgeData, vtkPoints *outputPts, vtkPointData *outputPD)
00393 {
00394 }

Generated on Sun Jun 22 12:13:09 2003 for Catmull Clark by doxygen 1.3.2