Voronoi 3D Manual
A Voronoi pattern segments the space into separate cells defined by a list of points. The maxon::Voronoi3DInterface allows to segment 3D space into such Voronoi cells.
The maxon::Voronoi3DInterface allows to collect points and to create 3D Voronoi cells around these points.
The points stored in the Voronoi object are handled with:
The calculation of Voronoi cells is divided into two steps:
The created cells are accessed with:
Further functions are:
A maxon::CellData object represents a single Voronoi cell:
A given cell can be handled with:
Two cells can be merged with:
Further functions are:
An edge within a cell is defined as a maxon::CellEdge :
// calculate size of the workspace which covers all points
// create and init Voronoi3DRef const maxon::Voronoi3DRef voronoi = maxon::Voronoi3DRef::Create() iferr_return ; voronoi.Init(workspace) iferr_return ;
// add points voronoi.AddPoints(points) iferr_return ;
// calculate result voronoi.CalcTetrahedralization() iferr_return ; voronoi.CalcCells() iferr_return ;
// check success const maxon :: Bool voronoiNotReady = !voronoi.IsReady(); if ( MAXON_UNLIKELY (voronoiNotReady)) return maxon ::UnexpectedError( MAXON_SOURCE_LOCATION );
// get cell data maxon ::BaseArray< maxon ::CellData>& curCellData = voronoi.GetCellDataStructure() iferr_return ;
// random generator for object color maxon ::LinearCongruentialRandom< maxon :: Float32 > randomGen;
// for each cell create a PolygonObject for (auto& cell : curCellData) { // check if the cell does not have "infinite" vertices in case of border cells auto CheckCell = [workspace]( const maxon::CellData & cellArg) -> maxon::Bool { const auto & vertices = cellArg.GetVertices(); for ( const maxon::Vector & pos : vertices) { if (!workspace. Contains (pos)) return false ; } return true ; };
// create PolygonObject for the given cells if (CheckCell(cell)) { const maxon::BaseArray<maxon::Vector> & vertices = cell.GetVertices(); const Int32 vertexCount = ( Int32 )vertices. GetCount ();
// allocate PolygonObject PolygonObject * const polygonObject = PolygonObject::Alloc (vertexCount, 0); if (polygonObject != nullptr ) { // prepare Modeling object to create ngons AutoAlloc<Modeling> modeling; if (modeling == nullptr ) return maxon::OutOfMemoryError( MAXON_SOURCE_LOCATION ); modeling-> InitObject (polygonObject);
// set points for ( maxon::Int32 i = 0; i < vertexCount; ++i) { modeling-> SetPoint (polygonObject, i, vertices[i]); }
// set ngons const maxon::BaseArray<Int> & faces = cell.GetFaces(); const maxon::BaseArray<maxon::CellEdge> & edges = cell.GetEdges(); const maxon::Int faceCount = faces. GetCount ();
// for each face create a ngon for ( maxon::Int i = 0; i < faceCount; ++i) { // set start edge maxon::Int currentEdgeIndex = faces[i]; const maxon::Int startEdgeIndex = currentEdgeIndex;
// array to store the ngon's vertex indices maxon::BaseArray<maxon::Int32> ngonIndices;
// loop over all edges of the ngon do { // append first vertex index const maxon::CellEdge & edge = edges[currentEdgeIndex]; ngonIndices. Append (( Int32 )edge. _start ) iferr_return ;
// get next edge currentEdgeIndex = edge. _nextEdgeOfFace ; } while (startEdgeIndex != currentEdgeIndex);
// create ngon const Int32 ngonIndexCount = ( Int32 )ngonIndices. GetCount (); if (ngonIndexCount > 0) { modeling-> CreateNgon (polygonObject, ngonIndices. GetFirst (), ngonIndexCount, MODELING_SETNGON_FLAG_TRIANGULATE ); } }
// finalize polygon object modeling-> Commit (polygonObject, MODELING_COMMIT_TRINGONS );
// create random color auto GetRandomColor = [&randomGen]() -> maxon::Vector { maxon::Vector color; color. x = (randomGen.Get01() * 0.5) + 0.5; color. y = (randomGen.Get01() * 0.5) + 0.5; color. z = (randomGen.Get01() * 0.5) + 0.5; return color; };
// set object color polygonObject-> SetParameter ( ID_BASEOBJECT_USECOLOR , ID_BASEOBJECT_USECOLOR_ALWAYS , DESCFLAGS_SET::NONE ); polygonObject-> SetParameter ( ID_BASEOBJECT_COLOR , GetRandomColor(), DESCFLAGS_SET::NONE ); // insert object into the scene doc->InsertObject(polygonObject, nullptr , nullptr ); } } }