本文是用vtk來實作的,首先通過公式計算出二維愛心的點,然後利用vtkParametricSpline類來将點連接配接起來,最後通過建立二維三角剖分然後再加了一些限制就完成啦,效果如下:
實作代碼如下
#include <vtkPolyData.h>
#include <vtkSmartPointer.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkProperty.h>
#include <vtkParametricSpline.h>
#include <vtkParametricFunctionSource.h>
#include <vtkSphereSource.h>
#include <vtkPlaneSource.h>
#include <vtkGlyph3DMapper.h>
#include <vtkFillHolesFilter.h>
#include <vtkFeatureEdges.h>
#include <vtkPolyDataNormals.h>
#include <vtkDelaunay2D.h>
#include <vtkVertexGlyphFilter.h>
#include <vtkPolygon.h>
#define PI 3.14159265358979323846
int main(int, char *[])
{
//存用公式計算出來的點
vtkSmartPointer<vtkPoints> points =
vtkSmartPointer<vtkPoints>::New();
// 建立一個平面來将愛心裡面填沖顔色
vtkSmartPointer<vtkPlaneSource> planeSource =
vtkSmartPointer<vtkPlaneSource>::New();
//限制突變性的形狀
vtkSmartPointer<vtkPolygon> poly =
vtkSmartPointer<vtkPolygon>::New();
//另一種心形,隻是沒有用線連接配接起來,它是用四塊區域拼湊起來的
//double x, y, x1, y1, y2;
//int X = 100, Y = 100;
//for (x = -360; x <= 360; x++)
//{
// x1 = x / 360.0;
// y1 = 360 * (pow(x1, 1.5) + pow(1 - x1 * x1, 0.5));
// y2 = 360 * (pow(x1, 1.5) - pow(1 - x1 * x1, 0.5));
// double p0[3] = { X + x / 18, Y + y1 / 9, 0 };
// double p1[3] = { X + x / 18, Y + y2 / 9, 0 };
// double p2[3] = { X - x / 18, Y + y1 / 9, 0 };
// double p3[3] = { X - x / 18, Y + y2 / 9, 0 };
//
// points->InsertNextPoint(p0);
// points->InsertNextPoint(p1);
// points->InsertNextPoint(p2);
// points->InsertNextPoint(p3);
//}
double a = 5; int i = 1;
for (double t = 0; t < 2 * PI; t += 0.21,i++)
{
//将二維坐标加入到point中
double x = a * (2 * sin(t) - sin(2 * t)), y = a * (2 * cos(t) - cos(2 * t));
double p0[3] = { x, y, 0 };
cout << x << " " << y << endl;
points->InsertNextPoint(p0);
}
cout << points->GetNumberOfPoints() << endl;
//用線将添加的點按順序連接配接起來
vtkSmartPointer<vtkParametricSpline> spline =
vtkSmartPointer<vtkParametricSpline>::New();
spline->SetPoints(points);
vtkSmartPointer<vtkPolyData> polydata =
vtkSmartPointer<vtkPolyData>::New();
polydata->SetPoints(points);
vtkSmartPointer<vtkVertexGlyphFilter> glyphFilter =
vtkSmartPointer<vtkVertexGlyphFilter>::New();
glyphFilter->SetInputData(polydata);
glyphFilter->Update();
//指定用于生成曲面細分的參數函數
vtkSmartPointer<vtkParametricFunctionSource> functionSource =
vtkSmartPointer<vtkParametricFunctionSource>::New();
functionSource->SetParametricFunction(spline);
functionSource->Update();
//這裡加了一些限制條件,按順序是點連接配接起來
for (int i = 29; i >0; i--)
{
poly->GetPointIds()->InsertNextId(i);
}
vtkSmartPointer<vtkCellArray> cell =
vtkSmartPointer<vtkCellArray>::New();
cell->InsertNextCell(poly); //設計拓撲結構
邊界限制
vtkSmartPointer<vtkPolyData> boundary =
vtkSmartPointer<vtkPolyData>::New();
boundary->SetPoints(points);
boundary->SetPolys(cell); //隻顯示具有拓撲結構部分
//得到最大的凸包
vtkSmartPointer<vtkDelaunay2D> content = vtkSmartPointer<vtkDelaunay2D>::New();
//content->SetInputConnection(functionSource->GetOutputPort());
content->SetInputData(polydata);
content->SetSourceData(boundary);
content->Update();
//用點練成的線的mapper,actor
vtkSmartPointer<vtkPolyDataMapper> splineMapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
splineMapper->SetInputConnection(functionSource->GetOutputPort());
vtkSmartPointer<vtkActor> splineActor =
vtkSmartPointer<vtkActor>::New();
splineActor->SetMapper(splineMapper);
splineActor->GetProperty()->SetColor(1,0,0);
vtkSmartPointer<vtkSphereSource> sphereSource =
vtkSmartPointer<vtkSphereSource>::New();
sphereSource->SetPhiResolution(21);
sphereSource->SetThetaResolution(21);
sphereSource->SetRadius(.05);
vtkSmartPointer<vtkPolyData> splinePointsData =
vtkSmartPointer<vtkPolyData>::New();
splinePointsData->SetPoints(points);
// 把中間的填滿
vtkSmartPointer<vtkPolyDataMapper> filledMapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
filledMapper->SetInputConnection(content->GetOutputPort());
vtkSmartPointer<vtkActor> filledActor =
vtkSmartPointer<vtkActor>::New();
filledActor->SetMapper(filledMapper);
//filledActor->GetProperty()->SetDiffuseColor(1.0, 0.3882, 0.2784);
filledActor->GetProperty()->SetColor(1, 0, 0);
vtkSmartPointer<vtkGlyph3DMapper> splinePointsMapper =
vtkSmartPointer<vtkGlyph3DMapper>::New();
splinePointsMapper->SetInputData(splinePointsData);
splinePointsMapper->SetSourceConnection(sphereSource->GetOutputPort());
vtkSmartPointer<vtkActor> pointsActor =
vtkSmartPointer<vtkActor>::New();
pointsActor->SetMapper(splinePointsMapper);
pointsActor->GetProperty()->SetColor(1, 0, 0);
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->SetSize(600, 600);
renderWindow->AddRenderer(renderer);
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);
renderer->AddActor(splineActor);
renderer->AddActor(pointsActor);
renderer->AddActor(filledActor);
renderWindow->Render();
renderWindowInteractor->Start();
return EXIT_SUCCESS;
}
轉載請标明出處。
參考文獻:
https://lorensen.github.io/VTKExamples/site/Cxx/Filtering/ConstrainedDelaunay2D/
https://shenchunxu.blog.csdn.net/article/details/54864771