15 #include <vtkCellData.h>
16 #include <vtkUnsignedCharArray.h>
17 #include <vtkPolyData.h>
42 return "Color variation";
47 return "color_variation_filter";
57 return "A filter to create variation of colors to a mesh. \n"
58 "The variation is applied as a normal distributin \n"
59 "with the original color as mean. A filter \n"
60 "is applied for smooth color transitions.";
66 "Select the global color variance", 10.0,
DoubleRange(1.0, 100.0, 0.5), 1.0, root);
73 "Select the local color variance", 1.0, DoubleRange(0.1, 10.0, 0.1), 1.0, root);
80 "Select the number of smoothing iterations", 3, DoubleRange(0, 10, 1), 0, root);
96 temp->setValueName(
"Input");
97 temp->setHelp(
"Input mesh to be applied color variation.");
106 temp->setValueName(
"Output");
107 temp->setHelp(
"Output mesh");
113 MeshPtr inputMesh = boost::dynamic_pointer_cast<StringPropertySelectMesh>(
mInputTypes[0])->getMesh();
117 double globaleVatiance = this->getGlobalVarianceOption(
mOptions)->getValue();
118 double localeVatiance = this->getLocalVarianceOption(
mOptions)->getValue();
119 int smoothingIterations = int(this->getSmoothingOption(
mOptions)->getValue());
121 mOutputMesh = this->
execute(inputMesh, globaleVatiance, localeVatiance, smoothingIterations);
133 vtkPolyDataPtr polyData = inputMesh->getTransformedPolyDataCopy(inputMesh->get_rMd());
134 mGlobalVariance = globaleVariance;
135 mLocalVariance = localeVariance;
137 this->sortPolyData(polyData);
138 this->colorPolyData(inputMesh);
139 this->smoothColorsInMesh(smoothingIterations);
140 polyData->GetCellData()->SetScalars(mColors);
147 outputMesh->setColor(inputMesh->getColor());
148 outputMesh->setUseColorFromPolydataScalars(
true);
149 outputMesh->get_rMd_History()->setParentSpace(inputMesh->getParentSpace());
170 mPolyToPointsArray.clear();
171 mPointToPolysArray.clear();
173 vtkIdType numberOfCells = polyData->GetNumberOfCells();
175 mPolyToPointsArray = std::vector<std::vector<vtkIdType>>(numberOfCells);
177 std::vector<std::vector<vtkIdType>> pointToPolysArray(polyData->GetNumberOfPoints());
178 for(vtkIdType i = 0; i < numberOfCells; i++)
180 vtkIdListPtr points = polyData->GetCell(i)->GetPointIds();
181 vtkIdType numberOfIds = points->GetNumberOfIds();
182 std::vector<vtkIdType> pointsArray(numberOfIds);
183 for(vtkIdType j = 0; j < numberOfIds; j++)
185 vtkIdType p = points->GetId(j);
187 pointToPolysArray[p].resize(pointToPolysArray[p].size()+1, i);
189 mPolyToPointsArray[i] = pointsArray;
191 mPointToPolysArray = pointToPolysArray;
197 if(mPolyToPointsArray.empty() || mPointToPolysArray.empty())
200 vtkPolyDataPtr polyData = mesh->getTransformedPolyDataCopy(Transform3D::Identity());
202 mAssignedColorValues.clear();
203 mColors = vtkUnsignedCharArrayPtr::New();
204 mColors->SetNumberOfComponents(3);
205 int numberOfPolys = polyData->GetNumberOfCells();
206 mColors->SetNumberOfTuples(numberOfPolys);
207 QColor originalColor = mesh->getColor();
209 mR_mean = originalColor.red();
210 mG_mean = originalColor.green();
211 mB_mean = originalColor.blue();
213 this->generateColorDistribution();
215 mAssignedColorValues.clear();
216 mAssignedColorValues = std::vector<bool>(numberOfPolys,
false);
218 for(
int i=0; i<numberOfPolys; i++)
219 if(!mAssignedColorValues[i])
220 for(
int j=0; j<mPolyToPointsArray[i].size(); j++)
221 this->applyColorToNeighbourPolys(mPolyToPointsArray[i][j], mR_mean, mG_mean, mB_mean);
226 void ColorVariationFilter::applyColorToNeighbourPolys(
int startIndex,
double R,
double G,
double B)
229 std::vector<vtkIdType> polyIndexColoringQueue = this->applyColorAndFindNeighbours(startIndex, R, G, B);
230 std::vector<double> color {R, G, B};
231 std::vector<std::vector<double>> polyColorColoringQueue(polyIndexColoringQueue.size(), color);
233 while(!polyIndexColoringQueue.empty())
235 std::vector<vtkIdType> neighbourPointsList = mPolyToPointsArray[polyIndexColoringQueue[0]];
237 for(
int i=0; i<neighbourPointsList.size(); i++)
239 std::vector<double> newColor = generateColor(polyColorColoringQueue[0][0], polyColorColoringQueue[0][1], polyColorColoringQueue[0][2]);
240 std::vector<vtkIdType> polyIndexToColor = this->applyColorAndFindNeighbours(neighbourPointsList[i], newColor[0], newColor[1], newColor[2]);
241 polyIndexColoringQueue.insert(polyIndexColoringQueue.end(), polyIndexToColor.begin(), polyIndexToColor.end());
242 polyColorColoringQueue.resize(polyColorColoringQueue.size()+polyIndexToColor.size(), newColor);
244 polyIndexColoringQueue.erase(polyIndexColoringQueue.begin());
245 polyColorColoringQueue.erase(polyColorColoringQueue.begin());
249 std::vector<vtkIdType> ColorVariationFilter::applyColorAndFindNeighbours(
int pointIndex,
double R,
double G,
double B)
251 std::vector<vtkIdType> neighbourPolysList = mPointToPolysArray[pointIndex];
252 std::vector<int> removeIndexList;
254 for(
int i=0; i<neighbourPolysList.size(); i++)
256 if(!mAssignedColorValues[neighbourPolysList[i]])
258 mColors->InsertTuple3(neighbourPolysList[i], R, G, B);
259 mAssignedColorValues[neighbourPolysList[i]] =
true;
263 removeIndexList.push_back(i);
267 int N = removeIndexList.size();
268 for(
int i=N-1; i>=0; i--)
269 neighbourPolysList.erase(neighbourPolysList.begin() + removeIndexList[i]);
271 return neighbourPolysList;
274 void ColorVariationFilter::generateColorDistribution()
276 mR_dist = std::normal_distribution<> {mR_mean, mGlobalVariance};
277 mG_dist = std::normal_distribution<> {mG_mean, mGlobalVariance};
278 mB_dist = std::normal_distribution<> {mB_mean, mGlobalVariance};
281 std::vector<double> ColorVariationFilter::generateColor(
double R,
double G,
double B)
284 std::vector<double> color;
285 color.push_back( std::max(std::min( std::max(std::min(mR_dist(m_gen),R+mLocalVariance),R-mLocalVariance) ,254.999),0.0001) );
286 color.push_back( std::max(std::min( std::max(std::min(mG_dist(m_gen),G+mLocalVariance),G-mLocalVariance) ,254.999),0.0001) );
287 color.push_back( std::max(std::min( std::max(std::min(mB_dist(m_gen),B+mLocalVariance),B-mLocalVariance) ,254.999),0.0001) );
292 void ColorVariationFilter::smoothColorsInMesh(
int iterations)
294 for(
int itr=0; itr<iterations; itr++)
297 int numberofPolys = newColors->GetNumberOfTuples();
299 Eigen::MatrixXd allColors(numberofPolys,3);
300 for(
int i=0; i<numberofPolys; i++)
302 double colorTuple[3];
303 mColors->GetTuple(i, colorTuple);
304 allColors(i,0) = colorTuple[0];
305 allColors(i,1) = colorTuple[1];
306 allColors(i,2) = colorTuple[2];
309 for(
int i=0; i<numberofPolys; i++)
311 std::vector<vtkIdType> connectedPoints = mPolyToPointsArray[i];
312 std::vector<int> neighbourPolys;
313 for(
int j=0; j<connectedPoints.size(); j++)
315 std::vector<vtkIdType> newNeighbours = mPointToPolysArray[connectedPoints[j]];
316 neighbourPolys.insert(neighbourPolys.end(), newNeighbours.begin(), newNeighbours.end());
318 neighbourPolys.erase( unique( neighbourPolys.begin(), neighbourPolys.end() ), neighbourPolys.end() );
319 std::vector<std::vector<double>> neighbourColors;
320 Eigen::Vector3d sumNeighbourColors = Eigen::Vector3d::Zero();
321 for(
int j=0; j<neighbourPolys.size(); j++)
323 sumNeighbourColors(0) += allColors(neighbourPolys[j],0);
324 sumNeighbourColors(1) += allColors(neighbourPolys[j],1);
325 sumNeighbourColors(2) += allColors(neighbourPolys[j],2);
328 Eigen::Vector3d color;
329 for(
int j=0; j<3; j++)
330 color(j) = ( sumNeighbourColors(j) + allColors(i,j) ) / (neighbourPolys.size() + 1);
332 newColors->InsertTuple3(i, color[0], color[1], color[2]);