/*========================================================================= Program: Visualization Toolkit Module: $RCSfile: vtkShrinkPolyData.cxx,v $ Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkShrinkPolyData.h" #include "vtkCellArray.h" #include "vtkCellData.h" #include "vtkInformation.h" #include "vtkInformationVector.h" #include "vtkObjectFactory.h" #include "vtkPointData.h" #include "vtkPolyData.h" vtkCxxRevisionMacro(vtkShrinkPolyData, "$Revision: 1.69 $"); vtkStandardNewMacro(vtkShrinkPolyData); vtkShrinkPolyData::vtkShrinkPolyData(double sf) { sf = ( sf < 0.0 ? 0.0 : (sf > 1.0 ? 1.0 : sf)); this->ShrinkFactor = sf; } template void vtkShrinkPolyDataExecute(vtkShrinkPolyData *self, T *inPts, double shrinkFactor, vtkInformation *inInfo, vtkInformation *outInfo) { int j, k; T center[3]; int abortExecute=0; vtkCellArray *newVerts, *newLines, *newPolys; vtkPointData *pd; vtkCellArray *inVerts,*inLines,*inPolys,*inStrips; vtkIdType numNewPts, numNewLines, numNewPolys, polyAllocSize; vtkIdType npts = 0; vtkIdType *pts = 0; vtkIdType newIds[3]; vtkPoints *newPoints; T *p1, *p2, *p3; vtkPolyData *input = vtkPolyData::SafeDownCast( inInfo->Get(vtkDataObject::DATA_OBJECT())); vtkPolyData *output= vtkPolyData::SafeDownCast( outInfo->Get(vtkDataObject::DATA_OBJECT())); vtkPointData *pointData = output->GetPointData(); pd = input->GetPointData(); inVerts = input->GetVerts(); inLines = input->GetLines(); inPolys = input->GetPolys(); inStrips = input->GetStrips(); // Count the number of new points and other primitives that // need to be created. // numNewPts = input->GetNumberOfVerts(); numNewLines = 0; numNewPolys = 0; polyAllocSize = 0; for (inLines->InitTraversal(); inLines->GetNextCell(npts,pts); ) { numNewPts += (npts-1) * 2; numNewLines += npts - 1; } for (inPolys->InitTraversal(); inPolys->GetNextCell(npts,pts); ) { numNewPts += npts; numNewPolys++; polyAllocSize += npts + 1; } for (inStrips->InitTraversal(); inStrips->GetNextCell(npts,pts); ) { numNewPts += (npts-2) * 3; polyAllocSize += (npts - 2) * 4; } // Allocate // newVerts = vtkCellArray::New(); newVerts->Allocate(input->GetNumberOfVerts()); newLines = vtkCellArray::New(); newLines->Allocate(numNewLines*3); newPolys = vtkCellArray::New(); newPolys->Allocate(polyAllocSize); pointData->CopyAllocate(pd); newPoints = input->GetPoints()->NewInstance(); newPoints->SetDataType(input->GetPoints()->GetDataType()); newPoints->Allocate(numNewPts); newPoints->SetNumberOfPoints(numNewPts); T *outPts = (T *)newPoints->GetVoidPointer(0); vtkIdType outCount = 0; // Copy vertices (no shrinking necessary) // for (inVerts->InitTraversal(); inVerts->GetNextCell(npts,pts) && !abortExecute; ) { newVerts->InsertNextCell(npts); for (j=0; jInsertCellPoint(outCount); pointData->CopyData(pd,pts[j],outCount); outCount++; } abortExecute = self->GetAbortExecute(); } self->UpdateProgress (0.10); // Lines need to be shrunk, and if polyline, split into separate pieces // for (inLines->InitTraversal(); inLines->GetNextCell(npts,pts) && !abortExecute; ) { for (j=0; j<(npts-1); j++) { p1 = inPts + pts[j]*3; p2 = inPts + pts[j+1]*3; for (k=0; k<3; k++) { center[k] = (p1[k] + p2[k]) / 2; } for (k=0; k<3; k++) { outPts[k] = (T)(center[k] + shrinkFactor*(p1[k] - center[k])); } outPts += 3; pointData->CopyData(pd,pts[j],outCount); outCount++; for (k=0; k<3; k++) { outPts[k] = (T)(center[k] + shrinkFactor*(p2[k] - center[k])); } outPts += 3; pointData->CopyData(pd,pts[j+1],outCount); newIds[0] = outCount - 1; newIds[1] = outCount; newLines->InsertNextCell(2,newIds); outCount++; } abortExecute = self->GetAbortExecute(); } self->UpdateProgress (0.25); // Polygons need to be shrunk // for (inPolys->InitTraversal(); inPolys->GetNextCell(npts,pts) && !abortExecute; ) { for (center[0]=center[1]=center[2]=0, j=0; jInsertNextCell(npts); for (j=0; jInsertCellPoint(outCount); pointData->CopyData(pd,pts[j],outCount); outCount++; } abortExecute = self->GetAbortExecute(); } self->UpdateProgress (0.75); // Triangle strips need to be shrunk and split into separate pieces. // vtkIdType tmp; for (inStrips->InitTraversal(); inStrips->GetNextCell(npts,pts) && !abortExecute; ) { for (j=0; j<(npts-2); j++) { p1 = inPts + pts[j]*3; p2 = inPts + pts[j+1]*3; p3 = inPts + pts[j+2]*3; for (k=0; k<3; k++) { center[k] = (p1[k] + p2[k] + p3[k]) / 3; } for (k=0; k<3; k++) { outPts[k] = (T)(center[k] + shrinkFactor*(p1[k] - center[k])); } outPts += 3; pointData->CopyData(pd,pts[j],outCount); newIds[0] = outCount; outCount++; for (k=0; k<3; k++) { outPts[k] = (T)(center[k] + shrinkFactor*(p2[k] - center[k])); } outPts += 3; pointData->CopyData(pd,pts[j+1],outCount); newIds[1] = outCount; outCount++; for (k=0; k<3; k++) { outPts[k] = (T)(center[k] + shrinkFactor*(p3[k] - center[k])); } outPts += 3; pointData->CopyData(pd,pts[j+2],outCount); newIds[1] = outCount; outCount++; // must reverse order for every other triangle if (j%2) { tmp = newIds[0]; newIds[0] = newIds[2]; newIds[2] = tmp; } newPolys->InsertNextCell(3,newIds); } abortExecute = self->GetAbortExecute(); } // Update self and release memory // output->SetPoints(newPoints); newPoints->Delete(); output->SetVerts(newVerts); newVerts->Delete(); output->SetLines(newLines); newLines->Delete(); output->SetPolys(newPolys); newPolys->Delete(); output->GetCellData()->PassData(input->GetCellData()); } int vtkShrinkPolyData::RequestData( vtkInformation *vtkNotUsed(request), vtkInformationVector **inputVector, vtkInformationVector *outputVector) { // get the info objects vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); vtkInformation *outInfo = outputVector->GetInformationObject(0); // get the input vtkPolyData *input = vtkPolyData::SafeDownCast( inInfo->Get(vtkDataObject::DATA_OBJECT())); // Initialize vtkDebugMacro(<<"Shrinking polygonal data"); if (input == NULL || input->GetPoints() == NULL) { return 1; } // get the input pointer for templating void *inPtr = input->GetPoints()->GetVoidPointer(0); // call templated function switch (input->GetPoints()->GetDataType()) { vtkTemplateMacro( vtkShrinkPolyDataExecute(this, (VTK_TT *)(inPtr), this->ShrinkFactor, inInfo, outInfo)); default: break; } return 1; } void vtkShrinkPolyData::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "Shrink Factor: " << this->ShrinkFactor << "\n"; }