00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
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
00052 vtkObject* ret = vtkObjectFactory::CreateInstance("vtkCatmullClarkFilter");
00053 if(ret)
00054 {
00055 return (vtkCatmullClarkFilter*)ret;
00056 }
00057
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))) {
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) {
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
00144 input->BuildLinks();
00145
00146
00147 vtkPoints *outputPoints = vtkPoints::New();
00148 vtkCellArray *outputPolys = vtkCellArray::New();
00149
00150
00151
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
00160 for (int i = 0; i < countInputCells; i++) {
00161
00162
00163 vtkGenericCell *cell = vtkGenericCell::New();
00164 input->GetCell(i, cell);
00165
00166
00167 int cpoints = cell->GetNumberOfPoints();
00168
00169
00170
00171
00172
00173 float *facePoint = new float[3];
00174 computeFacePoint(cell, facePoint);
00175 cells[i].facePoint = outputPoints->InsertNextPoint(facePoint);
00176
00177
00178
00179
00180 for (int j = 0; j < cpoints; ++j) {
00181
00182
00183 vtkIdType id1 = cell->GetPointId(j);
00184 vtkIdType id2 = cell->GetPointId((j+1) % cpoints);
00185
00186
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);
00193 edgePoint = findEdgePoint(cells[neighbor], id1, id2);
00194 }
00195
00196 if (edgePoint == NULL) {
00197
00198
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 {
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
00234
00235 for (int j = 0; j < cpoints; ++j) {
00236
00237
00238 vtkIdType id = cell->GetPointId(j);
00239
00240
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) {
00253
00254 float *coord = new float[3];
00255 coord[0] = 0.0f;
00256 coord[1] = 0.0f;
00257 coord[2] = 0.0f;
00258
00259
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
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
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
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
00301
00302
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
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
00348 output->SetPoints(outputPoints);
00349 output->SetPolys(outputPolys);
00350
00351
00352
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
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 }