//---------------------------------------------------------------------------- Delaunay2DWindow::Delaunay2DWindow(Parameters& parameters) : Window(parameters), mTextColor(0.0f, 0.0f, 0.0f, 1.0f), mCurrentTriX(-1), mCurrentTriY(-1), mCurrentIndex(0) { #if 1 // Randomly generated points. std::mt19937 mte; std::uniform_real_distribution<float> rnd(0.125f, 0.875f); mVertices.resize(256); for (auto& v : mVertices) { v[0] = mXSize*rnd(mte); v[1] = mYSize*rnd(mte); } #endif #if 0 // A 3x3 square grid. mVertices.resize(9); mVertices[0] = Vector2<float>( 64.0f, 64.0f); mVertices[1] = Vector2<float>( 64.0f, 256.0f); mVertices[2] = Vector2<float>( 64.0f, 448.0f); mVertices[3] = Vector2<float>(256.0f, 64.0f); mVertices[4] = Vector2<float>(256.0f, 256.0f); mVertices[5] = Vector2<float>(256.0f, 448.0f); mVertices[6] = Vector2<float>(448.0f, 64.0f); mVertices[7] = Vector2<float>(448.0f, 256.0f); mVertices[8] = Vector2<float>(448.0f, 448.0f); #endif mDelaunay(static_cast<int>(mVertices.size()), &mVertices[0], 0.001f); if (mDelaunay.GetDimension() == 2) { mDelaunay.GetHull(mHull); } else { LogError("Degenerate point set."); parameters.created = false; return; } mInfo.initialTriangle = -1; mInfo.finalTriangle = 0; mOverlay.reset(new OverlayEffect(mXSize, mYSize, mXSize, mYSize, SamplerState::MIN_P_MAG_P_MIP_P, SamplerState::CLAMP, SamplerState::CLAMP, true)); mScreenTexture.reset(new Texture2(DF_R8G8B8A8_UNORM, mXSize, mYSize)); mScreenTexture->SetUsage(Resource::DYNAMIC_UPDATE); mOverlay->SetTexture(mScreenTexture); mScreenTexels = mScreenTexture->Get<unsigned int>(); }
ConstrainedDelaunay2DWindow::ConstrainedDelaunay2DWindow( Parameters& parameters) : Window(parameters), mTextColor({ 0.0f, 0.0f, 0.0f, 1.0f }), mCurrentTriX(-1), mCurrentTriY(-1), mCurrentIndex(0) { // Randomly generated points. std::mt19937 mte; std::uniform_real_distribution<float> rnd(0.125f, 0.875f); mVertices.resize(256); for (auto& v : mVertices) { v[0] = mXSize*rnd(mte); v[1] = mYSize*rnd(mte); } int numVertices = static_cast<int>(mVertices.size()); mDelaunay(numVertices, &mVertices[0], 0.001f); if (mDelaunay.GetDimension() == 2) { mDelaunay.GetHull(mHull); } else { LogError("Degenerate point set."); parameters.created = false; return; } mInfo.initialTriangle = -1; mInfo.finalTriangle = 0; mOverlay = std::make_shared<OverlayEffect>(mProgramFactory, mXSize, mYSize, mXSize, mYSize, SamplerState::MIN_P_MAG_P_MIP_P, SamplerState::CLAMP, SamplerState::CLAMP, true); mScreenTexture = std::make_shared<Texture2>(DF_R8G8B8A8_UNORM, mXSize, mYSize); mScreenTexture->SetUsage(Resource::DYNAMIC_UPDATE); mOverlay->SetTexture(mScreenTexture); mScreenTexels = mScreenTexture->Get<unsigned int>(); }
bool Delaunay3DWindow::CreateScene() { #if 1 // Randomly generated points in the cube [-1,1]^3. (0,0,0) is added to // ensure the hull contains the origin and the virtual trackball display // appears centered. std::mt19937 mte; std::uniform_real_distribution<float> rnd(-1.0f, 1.0f); mVertices.resize(128); for (auto& v : mVertices) { for (int j = 0; j < 3; ++j) { v[j] = rnd(mte); } } mVertices[0] = Vector3<float>::Zero(); #endif #if 0 // A cube with 3x3x3 points. mVertices.resize(27); for (int z = 0, i = 0; z < 3; ++z) { float fz = z - 1.0f; for (int y = 0; y < 3; ++y) { float fy = y - 1.0f; for (int x = 0; x < 3; ++x, ++i) { float fx = x - 1.0f; mVertices[i] = Vector3<float>(fx, fy, fz); } } } #endif #if 0 // Some pathological examples (needle-like configurations). //std::string filename = "data1.txt"; std::string filename = "data2.txt"; //std::string filename = "data3.txt"; std::string path = mEnvironment.GetPath(filename); if (path == "") { LogError("Cannot find file " + filename + "."); return false; } std::ifstream input(path); int numVertices; input >> numVertices; mVertices.resize(numVertices); for (int i = 0; i < numVertices; ++i) { for (int j = 0; j < 3; ++j) { input >> mVertices[i][j]; } } #endif Vector3<float> vmin, vmax; ComputeExtremes((int)mVertices.size(), &mVertices[0], vmin, vmax); for (int j = 0; j < 3; ++j) { mRandom[j] = std::uniform_real_distribution<float>(vmin[j], vmax[j]); } mDelaunay(static_cast<int>(mVertices.size()), &mVertices[0], 0.001f); mInfo.initialTetrahedron = -1; mInfo.finalTetrahedron = 0; mWireTetra.resize(mDelaunay.GetNumTetrahedra()); mSolidTetra.resize(mDelaunay.GetNumTetrahedra()); mScene = std::make_shared<Node>(); CreateSphere(); mVCEffect = std::make_shared<VertexColorEffect>(mProgramFactory); for (int j = 0; j < mDelaunay.GetNumTetrahedra(); ++j) { CreateTetra(j); } mCameraRig.Subscribe(mWireTetra[0]->worldTransform, mVCEffect->GetPVWMatrixConstant()); mTrackball.Attach(mScene); mTrackball.Update(); return true; }
std::vector<Triangle> triangulate(const std::vector<Vec2f> & points, float resolution = 50.0f) { std::vector<Triangle> mTriangles; std::vector<Vec2f> mPoints = points; float mSize = mPoints.size(); float mCount = fMIN(resolution, mSize); tpp::Delaunay::Point mPoint; std::vector<tpp::Delaunay::Point> mVertices; for (int32_t i = 0; i < mCount; i++) { int32_t mId = (int32_t)((float)i / mCount * mSize); mPoint[0] = mPoints[mId].x; mPoint[1] = mPoints[mId].y; mVertices.push_back(mPoint); } tpp::Delaunay mDelaunay(mVertices); mDelaunay.Triangulate(); for (tpp::Delaunay::fIterator mTriIt = mDelaunay.fbegin(); mTriIt != mDelaunay.fend(); ++mTriIt) { int32_t mA = mDelaunay.Org(mTriIt); int32_t mB = mDelaunay.Dest(mTriIt); int32_t mC = mDelaunay.Apex(mTriIt); int32_t mAId = (int32_t)(((float)mA / resolution) * mSize); int32_t mBId = (int32_t)(((float)mB / resolution) * mSize); int32_t mCId = (int32_t)(((float)mC / resolution) * mSize); Vec2f mTriangle[3]; mTriangle[0] = Vec2f(mPoints[mAId].x, mPoints[mAId].y); mTriangle[1] = Vec2f(mPoints[mBId].x, mPoints[mBId].y); mTriangle[2] = Vec2f(mPoints[mCId].x, mPoints[mCId].y); Vec2f mCentroid = Vec2f( (mTriangle[0].x + mTriangle[1].x + mTriangle[2].x) / 3.0f, (mTriangle[0].y + mTriangle[1].y + mTriangle[2].y) / 3.0f ); int32_t mCounter = 0; Vec2f mPointA = mPoints[0]; Vec2f mPointB; for (int32_t i = 1; i < (int32_t)mSize; i++) { mPointB = mPoints[i]; if (mCentroid.y > fMIN(mPointA.y, mPointB.y) && mCentroid.y <= fMAX(mPointA.y, mPointB.y) && mCentroid.x <= fMAX(mPointA.x, mPointB.x) && mPointA.y != mPointB.y && (mPointA.x == mPointB.x || mCentroid.x <= (mCentroid.y - mPointA.y) * (mPointB.x - mPointA.x) / (mPointB.y - mPointA.y) + mPointA.x)) mCounter++; mPointA = mPointB; } if (mCounter % 2 != 0) { Triangle mTriData; float x0 = mTriangle[0].x; float y0 = mTriangle[0].y; float x1 = mTriangle[1].x; float y1 = mTriangle[1].y; float x2 = mTriangle[2].x; float y2 = mTriangle[2].y; if (((x1 - x0) * (y2 - y0) - (x2 -x0) * (y1 - y0)) > 0) { mTriData.a = Vec2f(x0, y0); mTriData.b = Vec2f(x1, y1); mTriData.c = Vec2f(x2, y2); } else { mTriData.a = Vec2f(x0, y0); mTriData.b = Vec2f(x2, y2); mTriData.c = Vec2f(x1, y1); } mTriangles.push_back(mTriData); } } return mTriangles; }