├── .gitignore ├── README.md ├── samples ├── Basic │ ├── include │ │ └── Resources.h │ ├── resources │ │ └── cinder_app_icon.ico │ ├── src │ │ └── BasicApp.cpp │ └── vc2013 │ │ ├── Basic.sln │ │ ├── Basic.vcxproj │ │ ├── Basic.vcxproj.filters │ │ └── Resources.rc └── SpherePoints │ ├── include │ └── Resources.h │ ├── resources │ └── cinder_app_icon.ico │ ├── src │ └── SpherePointsApp.cpp │ └── vc2013 │ ├── Resources.rc │ ├── SpherePoints.sln │ ├── SpherePoints.vcxproj │ └── SpherePoints.vcxproj.filters └── src ├── CiDelaunay.cpp ├── CiDelaunay.h └── Delaunay ├── Delaunay.cpp └── Delaunay.h /.gitignore: -------------------------------------------------------------------------------- 1 | x64 2 | *.suo 3 | *.opensdf 4 | *.sdf 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 | # Cinder-Delaunay 6 | 7 | Simple Delaunay triangulator for Cinder based on [Triangulate by Paul Bourke](http://paulbourke.net/papers/triangulate/) and [Gilles Dumoulin's C++ implementation](http://paulbourke.net/papers/triangulate/cpp.zip). Requires [Cinder glNext](https://github.com/cinder/Cinder/tree/glNext) 8 | 9 | ## Installation 10 | Clone into your blocks repo and add the following references to your project: 11 | * <cinder_root>\blocks\Cinder-Delaunay\src 12 | * <cinder_root>\blocks\Cinder-Delaunay\src\Delaunay 13 | 14 | ## Use 15 | Cinder-Delaunay has one main function, CiDelaunay::triangulate. Using it is as simple as: 16 | 17 | ``` 18 | TriMeshRef triangulatedPoints; 19 | 20 | void DelaunayApp::setup() 21 | { 22 | vector pointsToTriangulate; 23 | 24 | //fill vector with points, 25 | //then call: 26 | triangulatedPoints = CiDelaunay::triangulate(pointsToTriangulate); 27 | } 28 | 29 | void DelaunayApp::draw() 30 | { 31 | gl::enableWireframe(); 32 | gl::draw(triangulatedPoints); 33 | 34 | //or whatever you want to do with it 35 | } 36 | ``` 37 | Questions, comments, diatribes, feature requests, bugs'n'sugs? Send 'em to seth.gibson1@gmail.com. Also, I love PRs. 38 | 39 | 40 | -------------------------------------------------------------------------------- /samples/Basic/include/Resources.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "cinder/CinderResources.h" 3 | 4 | //#define RES_MY_RES CINDER_RESOURCE( ../resources/, image_name.png, 128, IMAGE ) 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /samples/Basic/resources/cinder_app_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SethGibson/Cinder-Delaunay/cede54c907a6d9429ce985820df2875a90594179/samples/Basic/resources/cinder_app_icon.ico -------------------------------------------------------------------------------- /samples/Basic/src/BasicApp.cpp: -------------------------------------------------------------------------------- 1 | #include "cinder/app/App.h" 2 | #include "cinder/app/RendererGl.h" 3 | #include "cinder/gl/gl.h" 4 | #include "cinder/gl/Batch.h" 5 | #include "cinder/gl/Shader.h" 6 | #include "cinder/Camera.h" 7 | #include "cinder/CameraUi.h" 8 | #include "cinder/Rand.h" 9 | 10 | #include "CiDelaunay.h" 11 | 12 | using namespace ci; 13 | using namespace ci::app; 14 | using namespace std; 15 | 16 | class BasicApp : public App 17 | { 18 | public: 19 | void setup() override; 20 | void update() override; 21 | void draw() override; 22 | 23 | private: 24 | void drawWorld(vec3 pCenter, vec3 pBounds, float pScale); 25 | 26 | vector mPoints; 27 | 28 | CameraPersp mCamera; 29 | CameraUi mCamUI; 30 | 31 | gl::VboRef mVbo; 32 | gl::VboMeshRef mMesh; 33 | gl::BatchRef mBatch; 34 | 35 | TriMeshRef mTris; 36 | }; 37 | 38 | int S_NUM_PTS = 1000; 39 | void BasicApp::setup() 40 | { 41 | getWindow()->setSize(1280, 720); 42 | 43 | 44 | 45 | vec3 cEyePos(0, 0, 10); 46 | mCamera.setPerspective(45.0f, getWindowAspectRatio(), 0.1f, 100.0f); 47 | mCamera.lookAt(cEyePos, vec3(0), vec3(0, 1, 0)); 48 | mCamera.setPivotDistance(length(cEyePos)); 49 | mCamUI = CameraUi(&mCamera, getWindow()); 50 | 51 | for (int i = 0; i < S_NUM_PTS; ++i) 52 | { 53 | mPoints.push_back(vec3(randFloat(-5, 5), randFloat(-5, 5), randFloat(0, 2))); 54 | } 55 | 56 | geom::BufferLayout cLayout; 57 | cLayout.append(geom::POSITION, 3, 0, 0, 0); 58 | mVbo = gl::Vbo::create(GL_ARRAY_BUFFER, mPoints, GL_STATIC_DRAW); 59 | mMesh = gl::VboMesh::create(S_NUM_PTS, GL_POINTS, { { cLayout, mVbo } }); 60 | 61 | string cVertShader = 62 | "uniform mat4 ciModelViewProjection;" 63 | "in vec4 ciPosition;" 64 | "void main()" 65 | "{ gl_Position = ciModelViewProjection*ciPosition; }"; 66 | string cFragShader = 67 | "out vec4 Color;" 68 | "void main()" 69 | "{ Color = vec4(1,1,1,1); }"; 70 | 71 | gl::GlslProgRef cShader = gl::GlslProg::create(cVertShader, cFragShader); 72 | mBatch = gl::Batch::create(mMesh, cShader); 73 | 74 | mTris = CiDelaunay::triangulate(mPoints); 75 | 76 | } 77 | 78 | void BasicApp::update() 79 | { 80 | } 81 | 82 | void BasicApp::draw() 83 | { 84 | gl::clear( Color( 0, 0, 0 ) ); 85 | gl::setMatrices(mCamera); 86 | 87 | drawWorld(vec3(0), vec3(10), 2.0f); 88 | gl::pointSize(4.0f); 89 | mBatch->draw(); 90 | 91 | gl::color(Color(0, 1, 1)); 92 | gl::enableWireframe(); 93 | gl::draw(*mTris.get()); 94 | 95 | 96 | } 97 | 98 | void BasicApp::drawWorld(vec3 pCenter, vec3 pBounds, float pScale) 99 | { 100 | gl::color(Color::white()); 101 | gl::drawStrokedCube(pCenter, pBounds); 102 | 103 | gl::color(Color(1, 0, 0)); 104 | gl::drawLine(pCenter, vec3(pScale, 0, 0)); 105 | gl::color(Color(0, 1, 0)); 106 | gl::drawLine(pCenter, vec3(0, pScale, 0)); 107 | gl::color(Color(0, 0, 1)); 108 | gl::drawLine(pCenter, vec3(0, 0, pScale)); 109 | } 110 | 111 | CINDER_APP( BasicApp, RendererGl ) 112 | -------------------------------------------------------------------------------- /samples/Basic/vc2013/Basic.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio 2013 3 | VisualStudioVersion = 12.0.31101.0 4 | MinimumVisualStudioVersion = 10.0.40219.1 5 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Basic", "Basic.vcxproj", "{A9C8E0C3-C9D3-4AC3-90AF-7773151D4E63}" 6 | EndProject 7 | Global 8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 9 | Debug|x64 = Debug|x64 10 | Release|x64 = Release|x64 11 | EndGlobalSection 12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 13 | {A9C8E0C3-C9D3-4AC3-90AF-7773151D4E63}.Debug|x64.ActiveCfg = Debug|x64 14 | {A9C8E0C3-C9D3-4AC3-90AF-7773151D4E63}.Debug|x64.Build.0 = Debug|x64 15 | {A9C8E0C3-C9D3-4AC3-90AF-7773151D4E63}.Release|x64.ActiveCfg = Release|x64 16 | {A9C8E0C3-C9D3-4AC3-90AF-7773151D4E63}.Release|x64.Build.0 = Release|x64 17 | EndGlobalSection 18 | GlobalSection(SolutionProperties) = preSolution 19 | HideSolutionNode = FALSE 20 | EndGlobalSection 21 | EndGlobal 22 | -------------------------------------------------------------------------------- /samples/Basic/vc2013/Basic.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | {A9C8E0C3-C9D3-4AC3-90AF-7773151D4E63} 15 | Basic 16 | Win32Proj 17 | 18 | 19 | 20 | Application 21 | false 22 | v120 23 | Unicode 24 | true 25 | 26 | 27 | Application 28 | true 29 | v120 30 | Unicode 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | <_ProjectFileVersion>10.0.30319.1 43 | true 44 | false 45 | 46 | 47 | 48 | Disabled 49 | ..\include;$(CINDER_DEV)\include;$(CINDER_DEV)\boost;$(CINDER_BLOCKS)\blocks\Cinder-Delaunay\src;$(CINDER_BLOCKS)\blocks\Cinder-Delaunay\src\Delaunay 50 | WIN32;_DEBUG;_WINDOWS;NOMINMAX;_WIN32_WINNT=0x0502;%(PreprocessorDefinitions) 51 | EnableFastChecks 52 | MultiThreadedDebug 53 | 54 | Level3 55 | ProgramDatabase 56 | true 57 | 58 | 59 | "..\..\..\..\..\..\Cinder\include";..\include 60 | 61 | 62 | cinder-$(PlatformToolset)_d.lib;OpenGL32.lib;%(AdditionalDependencies) 63 | $(CINDER_DEV)\lib\msw\$(PlatformTarget) 64 | true 65 | Windows 66 | false 67 | 68 | LIBCMT;LIBCPMT 69 | 70 | 71 | 72 | 73 | ..\include;$(CINDER_DEV)\include;$(CINDER_DEV)\boost;$(CINDER_BLOCKS)\blocks\Cinder-Delaunay\src;$(CINDER_BLOCKS)\blocks\Cinder-Delaunay\src\Delaunay 74 | WIN32;NDEBUG;_WINDOWS;NOMINMAX;_WIN32_WINNT=0x0502;%(PreprocessorDefinitions) 75 | MultiThreaded 76 | 77 | Level3 78 | ProgramDatabase 79 | true 80 | 81 | 82 | true 83 | 84 | 85 | "..\..\..\..\..\..\Cinder\include";..\include 86 | 87 | 88 | cinder-$(PlatformToolset).lib;OpenGL32.lib;%(AdditionalDependencies) 89 | $(CINDER_DEV)\lib\msw\$(PlatformTarget) 90 | false 91 | true 92 | Windows 93 | true 94 | 95 | false 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /samples/Basic/vc2013/Basic.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav 15 | 16 | 17 | {78f5f618-3b07-485c-85a6-73fcc776b124} 18 | 19 | 20 | {8c73c72e-8661-4048-962a-198d9afd3fa6} 21 | 22 | 23 | {894e9b6d-a79b-4ee2-990f-904822b3bd47} 24 | 25 | 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | Source Files\blocks\Cinder-Delaunay 38 | 39 | 40 | Source Files\blocks\Cinder-Delaunay\src 41 | 42 | 43 | 44 | 45 | Header Files 46 | 47 | 48 | Source Files\blocks\Cinder-Delaunay 49 | 50 | 51 | Source Files\blocks\Cinder-Delaunay\src 52 | 53 | 54 | 55 | 56 | Resource Files 57 | 58 | 59 | -------------------------------------------------------------------------------- /samples/Basic/vc2013/Resources.rc: -------------------------------------------------------------------------------- 1 | #include "../include/Resources.h" 2 | 3 | 1 ICON "..\\resources\\cinder_app_icon.ico" 4 | -------------------------------------------------------------------------------- /samples/SpherePoints/include/Resources.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "cinder/CinderResources.h" 3 | 4 | //#define RES_MY_RES CINDER_RESOURCE( ../resources/, image_name.png, 128, IMAGE ) 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /samples/SpherePoints/resources/cinder_app_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SethGibson/Cinder-Delaunay/cede54c907a6d9429ce985820df2875a90594179/samples/SpherePoints/resources/cinder_app_icon.ico -------------------------------------------------------------------------------- /samples/SpherePoints/src/SpherePointsApp.cpp: -------------------------------------------------------------------------------- 1 | #include "cinder/app/App.h" 2 | #include "cinder/app/RendererGl.h" 3 | #include "cinder/Camera.h" 4 | #include "cinder/CameraUi.h" 5 | #include "cinder/gl/gl.h" 6 | #include "cinder/gl/Batch.h" 7 | #include "cinder/gl/GlslProg.h" 8 | #include "cinder/Rand.h" 9 | #include "CiDelaunay.h" 10 | 11 | using namespace ci; 12 | using namespace ci::app; 13 | using namespace std; 14 | 15 | class SpherePointsApp : public App 16 | { 17 | public: 18 | void setup() override; 19 | void mouseDown( MouseEvent event ) override; 20 | void update() override; 21 | void draw() override; 22 | 23 | private: 24 | void drawWorld(vec3 pCenter, vec3 pBounds, float pAxes); 25 | 26 | vector mSpherePoints; 27 | gl::BatchRef mBatch; 28 | CameraPersp mCamera; 29 | CameraUi mCamUI; 30 | 31 | TriMeshRef mTris; 32 | }; 33 | 34 | int S_NUM_PTS = 1000; 35 | 36 | void SpherePointsApp::setup() 37 | { 38 | getWindow()->setSize(1280, 720); 39 | 40 | for (int i = 0; i < S_NUM_PTS; ++i) 41 | { 42 | float z = randFloat(-1.f, 1.f); 43 | float t = randFloat(0, 2.0f*M_PI); 44 | float r = math::sqrt(1.0f - z*z); 45 | float x = r*cos(t); 46 | float y = r*sin(t); 47 | if (x!=0&&y!=0&&z!=0) 48 | mSpherePoints.push_back(vec3(x*5.f, y*5.f, math::abs(z*5.f))); 49 | 50 | } 51 | 52 | gl::VboRef cVbo = gl::Vbo::create(GL_ARRAY_BUFFER, mSpherePoints, GL_STATIC_DRAW); 53 | geom::BufferLayout cAttribs; 54 | cAttribs.append(geom::POSITION,3,0,0,0); 55 | gl::VboMeshRef cMesh = gl::VboMesh::create(S_NUM_PTS, GL_POINTS, { { cAttribs, cVbo } }); 56 | 57 | string cVertShader = 58 | "uniform mat4 ciModelViewProjection;" 59 | "in vec4 ciPosition;" 60 | "void main(){" 61 | "gl_Position = ciModelViewProjection*ciPosition;}"; 62 | string cFragShader = 63 | "out vec4 Color;" 64 | "void main(){" 65 | "Color = vec4(1,1,1,1);}"; 66 | 67 | mBatch = gl::Batch::create(cMesh, gl::GlslProg::create(cVertShader, cFragShader)); 68 | 69 | 70 | vec3 cEyePos(0, 0, 10); 71 | mCamera.setPerspective(45.0f, getWindowAspectRatio(), 0.1f, 100.0f); 72 | mCamera.lookAt(cEyePos, vec3(0), vec3(0, 1, 0)); 73 | mCamera.setPivotDistance(length(cEyePos)); 74 | mCamUI = CameraUi(&mCamera, getWindow()); 75 | 76 | mTris = CiDelaunay::triangulate(mSpherePoints); 77 | } 78 | 79 | void SpherePointsApp::mouseDown( MouseEvent event ) 80 | { 81 | } 82 | 83 | void SpherePointsApp::update() 84 | { 85 | } 86 | 87 | void SpherePointsApp::draw() 88 | { 89 | gl::clear( Color( 0, 0, 0 ) ); 90 | gl::setMatrices(mCamera); 91 | 92 | drawWorld(vec3(0), vec3(10), 2.0f); 93 | 94 | gl::color(Color(0, 0.5f, 0.8f)); 95 | gl::enableWireframe(); 96 | gl::draw(*mTris); 97 | gl::disableWireframe(); 98 | 99 | gl::color(Color::white()); 100 | gl::pointSize(3.0f); 101 | mBatch->draw(); 102 | } 103 | 104 | void SpherePointsApp::drawWorld(vec3 pCenter, vec3 pBounds, float pAxes) 105 | { 106 | gl::pushMatrices(); 107 | gl::translate(pCenter); 108 | gl::color(Color::white()); 109 | gl::drawStrokedCube(vec3(0), pBounds); 110 | 111 | gl::color(Color(1, 0, 0)); 112 | gl::drawLine(vec3(0), vec3(pAxes,0,0)); 113 | gl::color(Color(0, 1, 0)); 114 | gl::drawLine(vec3(0), vec3(0, pAxes, 0)); 115 | gl::color(Color(0, 0, 1)); 116 | gl::drawLine(vec3(0), vec3(0, 0, pAxes)); 117 | gl::popMatrices(); 118 | 119 | } 120 | CINDER_APP( SpherePointsApp, RendererGl ) 121 | -------------------------------------------------------------------------------- /samples/SpherePoints/vc2013/Resources.rc: -------------------------------------------------------------------------------- 1 | #include "../include/Resources.h" 2 | 3 | 1 ICON "..\\resources\\cinder_app_icon.ico" 4 | -------------------------------------------------------------------------------- /samples/SpherePoints/vc2013/SpherePoints.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio 2013 3 | VisualStudioVersion = 12.0.31101.0 4 | MinimumVisualStudioVersion = 10.0.40219.1 5 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SpherePoints", "SpherePoints.vcxproj", "{B76A7C5C-999A-4FF1-82E7-B6C91DFC14F0}" 6 | EndProject 7 | Global 8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 9 | Debug|x64 = Debug|x64 10 | Release|x64 = Release|x64 11 | EndGlobalSection 12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 13 | {B76A7C5C-999A-4FF1-82E7-B6C91DFC14F0}.Debug|x64.ActiveCfg = Debug|x64 14 | {B76A7C5C-999A-4FF1-82E7-B6C91DFC14F0}.Debug|x64.Build.0 = Debug|x64 15 | {B76A7C5C-999A-4FF1-82E7-B6C91DFC14F0}.Release|x64.ActiveCfg = Release|x64 16 | {B76A7C5C-999A-4FF1-82E7-B6C91DFC14F0}.Release|x64.Build.0 = Release|x64 17 | EndGlobalSection 18 | GlobalSection(SolutionProperties) = preSolution 19 | HideSolutionNode = FALSE 20 | EndGlobalSection 21 | EndGlobal 22 | -------------------------------------------------------------------------------- /samples/SpherePoints/vc2013/SpherePoints.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | {B76A7C5C-999A-4FF1-82E7-B6C91DFC14F0} 15 | SpherePoints 16 | Win32Proj 17 | 18 | 19 | 20 | Application 21 | false 22 | v120 23 | Unicode 24 | true 25 | 26 | 27 | Application 28 | true 29 | v120 30 | Unicode 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | <_ProjectFileVersion>10.0.30319.1 43 | true 44 | false 45 | 46 | 47 | 48 | Disabled 49 | ..\include;$(CINDER_DEV)\include;$(CINDER_DEV)\boost;$(CINDER_BLOCKS)\blocks\Cinder-Delaunay\src;$(CINDER_BLOCKS)\blocks\Cinder-Delaunay\src\Delaunay 50 | WIN32;_DEBUG;_WINDOWS;NOMINMAX;_WIN32_WINNT=0x0502;%(PreprocessorDefinitions) 51 | EnableFastChecks 52 | MultiThreadedDebug 53 | 54 | Level3 55 | ProgramDatabase 56 | true 57 | 58 | 59 | "$(CINDER_DEV)\include";..\include 60 | 61 | 62 | cinder-$(PlatformToolset)_d.lib;OpenGL32.lib;%(AdditionalDependencies) 63 | "$(CINDER_DEV)\lib\msw\$(PlatformTarget)" 64 | true 65 | Windows 66 | false 67 | 68 | LIBCMT;LIBCPMT 69 | 70 | 71 | 72 | 73 | ..\include;$(CINDER_DEV)\include;$(CINDER_DEV)\boost;$(CINDER_BLOCKS)\blocks\Cinder-Delaunay\src;$(CINDER_BLOCKS)\blocks\Cinder-Delaunay\src\Delaunay 74 | WIN32;NDEBUG;_WINDOWS;NOMINMAX;_WIN32_WINNT=0x0502;%(PreprocessorDefinitions) 75 | MultiThreaded 76 | 77 | Level3 78 | ProgramDatabase 79 | true 80 | 81 | 82 | true 83 | 84 | 85 | "$(CINDER_DEV)\include";..\include 86 | 87 | 88 | cinder-$(PlatformToolset).lib;OpenGL32.lib;%(AdditionalDependencies) 89 | "$(CINDER_DEV)\lib\msw\$(PlatformTarget)" 90 | false 91 | true 92 | Windows 93 | true 94 | 95 | false 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /samples/SpherePoints/vc2013/SpherePoints.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav 15 | 16 | 17 | {997e16a9-31d0-49d0-9d19-527f27ab32c2} 18 | 19 | 20 | {9fcf9b4c-0d2d-475a-a35f-d27c3c9da86e} 21 | 22 | 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Source Files\blocks\Cinder-Delaunay 35 | 36 | 37 | Source Files\blocks\Cinder-Delaunay 38 | 39 | 40 | 41 | 42 | Header Files 43 | 44 | 45 | Source Files\blocks\Cinder-Delaunay 46 | 47 | 48 | Source Files\blocks\Cinder-Delaunay 49 | 50 | 51 | 52 | 53 | Resource Files 54 | 55 | 56 | -------------------------------------------------------------------------------- /src/CiDelaunay.cpp: -------------------------------------------------------------------------------- 1 | #include "CiDelaunay.h" 2 | 3 | //////////////////////////////////////////////////////////////////////// 4 | // Wrapper for Delaunay::CircumCircle 5 | // Params: 6 | // vec2 pP: point to check 7 | // vec2 *pCP: vec2[3] containing the points of the CircumCircle 8 | // Returns: 9 | // pair.first: true if pP is inside pCP 10 | // pair.second: x = CircumCircle center x 11 | // y = CircumCircle center y 12 | // z=CircumCircle radius 13 | //////////////////////////////////////////////////////////////////////// 14 | pair 15 | CiDelaunay::isPointinCircumCircle(vec2 pP, vec2 *pCP) 16 | { 17 | 18 | double cCX, cCY, cCR; 19 | bool cIsInCircle = CircumCircle(pP.x, pP.y, pCP[0].x, pCP[0].y, pCP[1].x, pCP[1].y, pCP[2].x, pCP[2].y, cCX, cCY, cCR); 20 | 21 | return make_pair(cIsInCircle, vec3(cCX, cCY, cCR)); 22 | 23 | } 24 | /* 25 | /////////////////////////////////////////////////////////////////////////////// 26 | // Triangulate() : 27 | // Triangulation subroutine 28 | // Takes as input NV vertices in array pxyz 29 | // Returned is a list of ntri triangular faces in the array v 30 | // These triangles are arranged in a consistent clockwise order. 31 | // The triangle array 'v' should be malloced to 3 * nv 32 | // The vertex array pxyz must be big enough to hold 3 more points 33 | // The vertex array must be sorted in increasing x values say 34 | // 35 | // qsort(p,nv,sizeof(XYZ),XYZCompare); 36 | /////////////////////////////////////////////////////////////////////////////// 37 | int Triangulate(int nv, XYZ pxyz[], ITRIANGLE v[], int &ntri){ 38 | */ 39 | TriMeshRef 40 | CiDelaunay::triangulate(vector pVertices) 41 | { 42 | vector cXYZVerts; 43 | vector cTriangles; 44 | 45 | vector cVtxOutput; 46 | vector cIdxOutput; 47 | 48 | int cOutTriCount = -1; 49 | 50 | for (auto v = pVertices.begin(); v != pVertices.end();++v) 51 | { 52 | cXYZVerts.push_back(toXYZ(*v)); 53 | } 54 | 55 | cXYZVerts.push_back(XYZ()); cXYZVerts.push_back(XYZ()); cXYZVerts.push_back(XYZ()); 56 | cTriangles.resize(cXYZVerts.size() * 3); 57 | qsort(cXYZVerts.data(), cXYZVerts.size(), sizeof(XYZ), XYZCompare); 58 | 59 | Triangulate(pVertices.size(), cXYZVerts.data(), &cTriangles[0], cOutTriCount); 60 | 61 | for (auto xyz = cXYZVerts.begin(); xyz != cXYZVerts.end(); ++xyz) 62 | { 63 | cVtxOutput.push_back(fromXYZ(*xyz)); 64 | } 65 | 66 | for (auto tri = cTriangles.begin(); tri != cTriangles.end(); ++tri) 67 | { 68 | cIdxOutput.push_back(tri->p1); 69 | cIdxOutput.push_back(tri->p2); 70 | cIdxOutput.push_back(tri->p3); 71 | } 72 | 73 | TriMeshRef cTriangulatedMesh = TriMesh::create(TriMesh::Format().positions(3)); 74 | cTriangulatedMesh->appendVertices(cVtxOutput.data(), cVtxOutput.size()); 75 | cTriangulatedMesh->appendIndices(cIdxOutput.data(), cIdxOutput.size()); 76 | 77 | return cTriangulatedMesh; 78 | } 79 | 80 | // Utilities 81 | 82 | vec3 CiDelaunay::fromXYZ(XYZ pInput) 83 | { 84 | return vec3(pInput.x, pInput.y, pInput.z); 85 | } 86 | 87 | XYZ CiDelaunay::toXYZ(vec3 pInput) 88 | { 89 | XYZ ret; 90 | ret.x = pInput.x; ret.y = pInput.y; ret.z = pInput.z; 91 | return ret; 92 | } 93 | 94 | ivec2 CiDelaunay::fromIEDGE(IEDGE pInput) 95 | { 96 | return ivec2(pInput.p1, pInput.p2); 97 | } 98 | 99 | IEDGE CiDelaunay::toIEDGE(ivec2 pInput) 100 | { 101 | IEDGE ret; 102 | ret.p1 = pInput.x; ret.p2 = pInput.y; 103 | return ret; 104 | } 105 | 106 | ivec3 CiDelaunay::fromITRIANGLE(ITRIANGLE pInput) 107 | { 108 | return ivec3(pInput.p1, pInput.p2, pInput.p3); 109 | } 110 | 111 | ITRIANGLE CiDelaunay::toITRIANGLE(ivec3 pInput) 112 | { 113 | ITRIANGLE ret; 114 | ret.p1 = pInput.x; ret.p2 = pInput.y; ret.p3 = pInput.z; 115 | return ret; 116 | } 117 | -------------------------------------------------------------------------------- /src/CiDelaunay.h: -------------------------------------------------------------------------------- 1 | #ifndef __CI_DELAUNAY__ 2 | #define __CI_DELAUNAY__ 3 | 4 | #include 5 | #include "cinder\Vector.h" 6 | #include "cinder\CinderGlm.h" 7 | #include "cinder\TriMesh.h" 8 | #include "Delaunay.h" 9 | 10 | using namespace std; 11 | using namespace ci; 12 | 13 | 14 | namespace CiDelaunay 15 | { 16 | 17 | vec3 fromXYZ(XYZ pInput); 18 | XYZ toXYZ(vec3 pInput); 19 | 20 | ivec2 fromIEDGE(IEDGE pInput); 21 | IEDGE toIEDGE(ivec2 pInput); 22 | 23 | ivec3 fromITRIANGLE(ITRIANGLE pInput); 24 | ITRIANGLE toITRIANGLE(ivec3 pInput); 25 | 26 | pair isPointinCircumCircle(vec2 pPt, vec2 *pCP); 27 | TriMeshRef triangulate(vector pVertices); 28 | }; 29 | #endif -------------------------------------------------------------------------------- /src/Delaunay/Delaunay.cpp: -------------------------------------------------------------------------------- 1 | #include "Delaunay.h" 2 | 3 | using namespace std; 4 | 5 | //////////////////////////////////////////////////////////////////////// 6 | // CircumCircle() : 7 | // Return true if a point (xp,yp) is inside the circumcircle made up 8 | // of the points (x1,y1), (x2,y2), (x3,y3) 9 | // The circumcircle centre is returned in (xc,yc) and the radius r 10 | // Note : A point on the edge is inside the circumcircle 11 | //////////////////////////////////////////////////////////////////////// 12 | 13 | int CircumCircle(double xp, double yp, double x1, double y1, double x2, 14 | double y2, double x3, double y3, double &xc, double &yc, double &r){ 15 | double m1, m2, mx1, mx2, my1, my2; 16 | double dx, dy, rsqr, drsqr; 17 | 18 | /* Check for coincident points */ 19 | if(abs(y1 - y2) < EPSILON && abs(y2 - y3) < EPSILON) 20 | return(false); 21 | if(abs(y2-y1) < EPSILON){ 22 | m2 = - (x3 - x2) / (y3 - y2); 23 | mx2 = (x2 + x3) / 2.0; 24 | my2 = (y2 + y3) / 2.0; 25 | xc = (x2 + x1) / 2.0; 26 | yc = m2 * (xc - mx2) + my2; 27 | }else if(abs(y3 - y2) < EPSILON){ 28 | m1 = - (x2 - x1) / (y2 - y1); 29 | mx1 = (x1 + x2) / 2.0; 30 | my1 = (y1 + y2) / 2.0; 31 | xc = (x3 + x2) / 2.0; 32 | yc = m1 * (xc - mx1) + my1; 33 | }else{ 34 | m1 = - (x2 - x1) / (y2 - y1); 35 | m2 = - (x3 - x2) / (y3 - y2); 36 | mx1 = (x1 + x2) / 2.0; 37 | mx2 = (x2 + x3) / 2.0; 38 | my1 = (y1 + y2) / 2.0; 39 | my2 = (y2 + y3) / 2.0; 40 | xc = (m1 * mx1 - m2 * mx2 + my2 - my1) / (m1 - m2); 41 | yc = m1 * (xc - mx1) + my1; 42 | } 43 | dx = x2 - xc; 44 | dy = y2 - yc; 45 | rsqr = dx * dx + dy * dy; 46 | r = sqrt(rsqr); 47 | dx = xp - xc; 48 | dy = yp - yc; 49 | drsqr = dx * dx + dy * dy; 50 | return((drsqr <= rsqr) ? true : false); 51 | } 52 | /////////////////////////////////////////////////////////////////////////////// 53 | // Triangulate() : 54 | // Triangulation subroutine 55 | // Takes as input NV vertices in array pxyz 56 | // Returned is a list of ntri triangular faces in the array v 57 | // These triangles are arranged in a consistent clockwise order. 58 | // The triangle array 'v' should be malloced to 3 * nv 59 | // The vertex array pxyz must be big enough to hold 3 more points 60 | // The vertex array must be sorted in increasing x values say 61 | // 62 | // qsort(p,nv,sizeof(XYZ),XYZCompare); 63 | /////////////////////////////////////////////////////////////////////////////// 64 | 65 | int Triangulate(int nv, XYZ pxyz[], ITRIANGLE v[], int &ntri){ 66 | int *complete = NULL; 67 | IEDGE *edges = NULL; 68 | IEDGE *p_EdgeTemp; 69 | int nedge = 0; 70 | int trimax, emax = 200; 71 | int status = 0; 72 | int inside; 73 | int i, j, k; 74 | double xp, yp, x1, y1, x2, y2, x3, y3, xc, yc, r; 75 | double xmin, xmax, ymin, ymax, xmid, ymid; 76 | double dx, dy, dmax; 77 | 78 | /* Allocate memory for the completeness list, flag for each triangle */ 79 | trimax = 4 * nv; 80 | complete = new int[trimax]; 81 | /* Allocate memory for the edge list */ 82 | edges = new IEDGE[emax]; 83 | /* 84 | Find the maximum and minimum vertex bounds. 85 | This is to allow calculation of the bounding triangle 86 | */ 87 | xmin = pxyz[0].x; 88 | ymin = pxyz[0].y; 89 | xmax = xmin; 90 | ymax = ymin; 91 | for(i = 1; i < nv; i++){ 92 | if (pxyz[i].x < xmin) xmin = pxyz[i].x; 93 | if (pxyz[i].x > xmax) xmax = pxyz[i].x; 94 | if (pxyz[i].y < ymin) ymin = pxyz[i].y; 95 | if (pxyz[i].y > ymax) ymax = pxyz[i].y; 96 | } 97 | dx = xmax - xmin; 98 | dy = ymax - ymin; 99 | dmax = (dx > dy) ? dx : dy; 100 | xmid = (xmax + xmin) / 2.0; 101 | ymid = (ymax + ymin) / 2.0; 102 | /* 103 | Set up the supertriangle 104 | his is a triangle which encompasses all the sample points. 105 | The supertriangle coordinates are added to the end of the 106 | vertex list. The supertriangle is the first triangle in 107 | the triangle list. 108 | */ 109 | pxyz[nv+0].x = xmid - 20 * dmax; 110 | pxyz[nv+0].y = ymid - dmax; 111 | pxyz[nv+1].x = xmid; 112 | pxyz[nv+1].y = ymid + 20 * dmax; 113 | pxyz[nv+2].x = xmid + 20 * dmax; 114 | pxyz[nv+2].y = ymid - dmax; 115 | v[0].p1 = nv; 116 | v[0].p2 = nv+1; 117 | v[0].p3 = nv+2; 118 | complete[0] = false; 119 | ntri = 1; 120 | /* 121 | Include each point one at a time into the existing mesh 122 | */ 123 | for(i = 0; i < nv; i++){ 124 | xp = pxyz[i].x; 125 | yp = pxyz[i].y; 126 | nedge = 0; 127 | /* 128 | Set up the edge buffer. 129 | If the point (xp,yp) lies inside the circumcircle then the 130 | three edges of that triangle are added to the edge buffer 131 | and that triangle is removed. 132 | */ 133 | for(j = 0; j < ntri; j++){ 134 | if(complete[j]) 135 | continue; 136 | x1 = pxyz[v[j].p1].x; 137 | y1 = pxyz[v[j].p1].y; 138 | x2 = pxyz[v[j].p2].x; 139 | y2 = pxyz[v[j].p2].y; 140 | x3 = pxyz[v[j].p3].x; 141 | y3 = pxyz[v[j].p3].y; 142 | inside = CircumCircle(xp, yp, x1, y1, x2, y2, x3, y3, xc, yc, r); 143 | if (xc + r < xp) 144 | // Suggested 145 | // if (xc + r + EPSILON < xp) 146 | complete[j] = true; 147 | if(inside){ 148 | /* Check that we haven't exceeded the edge list size */ 149 | if(nedge + 3 >= emax){ 150 | emax += 100; 151 | p_EdgeTemp = new IEDGE[emax]; 152 | for (int i = 0; i < nedge; i++) { // Fix by John Bowman 153 | p_EdgeTemp[i] = edges[i]; 154 | } 155 | delete []edges; 156 | edges = p_EdgeTemp; 157 | } 158 | edges[nedge+0].p1 = v[j].p1; 159 | edges[nedge+0].p2 = v[j].p2; 160 | edges[nedge+1].p1 = v[j].p2; 161 | edges[nedge+1].p2 = v[j].p3; 162 | edges[nedge+2].p1 = v[j].p3; 163 | edges[nedge+2].p2 = v[j].p1; 164 | nedge += 3; 165 | v[j] = v[ntri-1]; 166 | complete[j] = complete[ntri-1]; 167 | ntri--; 168 | j--; 169 | } 170 | } 171 | /* 172 | Tag multiple edges 173 | Note: if all triangles are specified anticlockwise then all 174 | interior edges are opposite pointing in direction. 175 | */ 176 | for(j = 0; j < nedge - 1; j++){ 177 | for(k = j + 1; k < nedge; k++){ 178 | if((edges[j].p1 == edges[k].p2) && (edges[j].p2 == edges[k].p1)){ 179 | edges[j].p1 = -1; 180 | edges[j].p2 = -1; 181 | edges[k].p1 = -1; 182 | edges[k].p2 = -1; 183 | } 184 | /* Shouldn't need the following, see note above */ 185 | if((edges[j].p1 == edges[k].p1) && (edges[j].p2 == edges[k].p2)){ 186 | edges[j].p1 = -1; 187 | edges[j].p2 = -1; 188 | edges[k].p1 = -1; 189 | edges[k].p2 = -1; 190 | } 191 | } 192 | } 193 | /* 194 | Form new triangles for the current point 195 | Skipping over any tagged edges. 196 | All edges are arranged in clockwise order. 197 | */ 198 | for(j = 0; j < nedge; j++) { 199 | if(edges[j].p1 < 0 || edges[j].p2 < 0) 200 | continue; 201 | v[ntri].p1 = edges[j].p1; 202 | v[ntri].p2 = edges[j].p2; 203 | v[ntri].p3 = i; 204 | complete[ntri] = false; 205 | ntri++; 206 | } 207 | } 208 | /* 209 | Remove triangles with supertriangle vertices 210 | These are triangles which have a vertex number greater than nv 211 | */ 212 | for(i = 0; i < ntri; i++) { 213 | if(v[i].p1 >= nv || v[i].p2 >= nv || v[i].p3 >= nv) { 214 | v[i] = v[ntri-1]; 215 | ntri--; 216 | i--; 217 | } 218 | } 219 | delete[] edges; 220 | delete[] complete; 221 | return 0; 222 | } 223 | 224 | void randomize(){ 225 | srand((time_t) time(NULL)); 226 | } 227 | 228 | int random(int n){ 229 | return rand()%n; 230 | } 231 | 232 | int XYZCompare(const void *v1, const void *v2){ 233 | XYZ *p1, *p2; 234 | 235 | p1 = (XYZ*)v1; 236 | p2 = (XYZ*)v2; 237 | if(p1->x < p2->x) 238 | return(-1); 239 | else if(p1->x > p2->x) 240 | return(1); 241 | else 242 | return(0); 243 | } 244 | 245 | void outputtriangle(int &nv, XYZ p[], ITRIANGLE v[], int &ntri){ 246 | int X, Y, i = 0; 247 | int max = 10; 248 | double x, y; 249 | 250 | for(int i = 0; i < ntri; i++){// replace cout by a compatible lineto to trace 251 | cout<<(int)p[v[i].p1].x<<" "<< (int)p[v[i].p1].y<<" "<< (int)p[v[i].p2].x 252 | <<" "<< (int)p[v[i].p2].y<<"\n"; 253 | cout<<(int)p[v[i].p2].x<<" "<< (int)p[v[i].p2].y<<" "<< (int)p[v[i].p3].x 254 | <<" "<< (int)p[v[i].p3].y<<"\n"; 255 | cout<<(int)p[v[i].p3].x<<" "<< (int)p[v[i].p3].y<<" "<< (int)p[v[i].p1].x 256 | <<" "<< (int)p[v[i].p1].y<<"\n"; 257 | } 258 | } 259 | 260 | int main(){ 261 | ITRIANGLE *v = NULL; 262 | int max = 10; 263 | XYZ *p = new XYZ[max]; 264 | XYZ *p_Temp = NULL; 265 | int nv = 0; 266 | int X, Y; 267 | int i; 268 | int ntri = 0; 269 | double x, y, z; 270 | bool b_Ok = false; 271 | 272 | randomize(); 273 | nv = 0; 274 | p = new XYZ[max]; 275 | while (nv != n_MaxPoints){ 276 | do{ 277 | b_Ok = true; 278 | x = (double)random(500); 279 | y = (double)random(500); 280 | for(int n_Cpt = 0; n_Cpt <= nv; n_Cpt++){ 281 | if((x == p[n_Cpt].x) && (y == p[n_Cpt].y)) b_Ok = false; 282 | }// to avoid similar points in the array 283 | }while(!b_Ok); 284 | if (nv >= max){ 285 | max = max * 2; // double the size of the array if necessary 286 | p_Temp = new XYZ[max]; 287 | for (int i = 0; i < nv; i++) { 288 | p_Temp[i] = p[i]; 289 | } 290 | delete []p; 291 | p = p_Temp; 292 | } 293 | p[nv].x = x * 1.0; 294 | p[nv].y = y * 1.0; 295 | nv++; 296 | } 297 | p_Temp = new XYZ[nv + 3]; 298 | for (int i = 0; i < nv; i++) { 299 | p_Temp[i] = p[i]; 300 | } 301 | delete []p; 302 | p = p_Temp; 303 | v = new ITRIANGLE[3 * nv]; 304 | qsort(p, nv, sizeof(XYZ), XYZCompare); 305 | Triangulate(nv, p, v, ntri); 306 | outputtriangle(nv, p, v, ntri); // use this fonction to trace the mesh (via 307 | delete []p;// OpenGL, DirectX, ...) 308 | delete []v; 309 | p = NULL; 310 | v = NULL; 311 | system("pause"); // remove under Linux 312 | return 0; 313 | } 314 | 315 | 316 | 317 | 318 | -------------------------------------------------------------------------------- /src/Delaunay/Delaunay.h: -------------------------------------------------------------------------------- 1 | #ifndef Delaunay_H 2 | #define Delaunay_H 3 | 4 | #include 5 | #include // for C qsort 6 | #include 7 | #include // for random 8 | 9 | const int MaxVertices = 500; 10 | const int MaxTriangles = 1000; 11 | const int n_MaxPoints = 10; // for the test programm 12 | const double EPSILON = 0.000001; 13 | 14 | struct ITRIANGLE 15 | { 16 | int p1, p2, p3; 17 | }; 18 | 19 | struct IEDGE 20 | { 21 | int p1, p2; 22 | }; 23 | 24 | struct XYZ 25 | { 26 | double x, y, z; 27 | }; 28 | 29 | int XYZCompare(const void *v1, const void *v2); 30 | int Triangulate(int nv, XYZ pxyz[], ITRIANGLE v[], int &ntri); 31 | int CircumCircle(double, double, double, double, double, double, double, 32 | double, double&, double&, double&); 33 | 34 | #endif 35 | --------------------------------------------------------------------------------