Voronoi 3D Manual

About

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.

Voronoi3DInterface

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:

CellData

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:

Example

// This example creates 3D Voronoi cells around the given points.
// The resulting geometry is copied to PolygonObjects.
// calculate size of the workspace which covers all points
MinMax mm;
for (maxon::Int i = 0; i != points.GetCount(); ++i)
{
mm.AddPoint(points[i]);
}
const maxon::Vector buffer(100.0, 100.0, 100.0);
workspace._minValue = mm.GetMin() - buffer;
workspace._maxValue = mm.GetMax() + buffer;
// 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)
{
// prepare Modeling object to create ngons
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
// 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
{
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_COLOR, GetRandomColor(), DESCFLAGS_SET::NONE);
// insert object into the scene
doc->InsertObject(polygonObject, nullptr, nullptr);
}
}
}

Further Reading