void Foam::DelaunayMeshTools::writeFixedPoints
(
    const fileName& fName,
    const Triangulation& t
)
{
    OFstream str(fName);

    Pout<< nl
        << "Writing fixed points to " << str.name() << endl;

    for
    (
        typename Triangulation::Finite_vertices_iterator vit =
            t.finite_vertices_begin();
        vit != t.finite_vertices_end();
        ++vit
    )
    {
        if (vit->fixed())
        {
            meshTools::writeOBJ(str, topoint(vit->point()));
        }
    }
}
Foam::tmp<Foam::Field<Type>> filterFarPoints
(
    const Triangulation& mesh,
    const Field<Type>& field
)
{
    tmp<Field<Type>> tNewField(new Field<Type>(field.size()));
    Field<Type>& newField = tNewField.ref();

    label added = 0;
    label count = 0;

    for
    (
        typename Triangulation::Finite_vertices_iterator vit =
            mesh.finite_vertices_begin();
        vit != mesh.finite_vertices_end();
        ++vit
    )
    {
        if (vit->real())
        {
            newField[added++] = field[count];
        }

        count++;
    }

    newField.resize(added);

    return tNewField;
}
void Foam::DelaunayMeshTools::writeInternalDelaunayVertices
(
    const fileName& instance,
    const Triangulation& t
)
{
    pointField internalDelaunayVertices(t.number_of_vertices());

    label vertI = 0;

    for
    (
        typename Triangulation::Finite_vertices_iterator vit =
            t.finite_vertices_begin();
        vit != t.finite_vertices_end();
        ++vit
    )
    {
        if (vit->internalPoint())
        {
            internalDelaunayVertices[vertI++] = topoint(vit->point());
        }
    }

    internalDelaunayVertices.setSize(vertI);

    pointIOField internalDVs
    (
        IOobject
        (
            "internalDelaunayVertices",
            instance,
            t.time(),
            IOobject::NO_READ,
            IOobject::AUTO_WRITE
        ),
        internalDelaunayVertices
    );

    Info<< nl
        << "Writing " << internalDVs.name()
        << " to " << internalDVs.instance()
        << endl;

    internalDVs.write();
}
void Foam::DelaunayMeshTools::writeOBJ
(
    const fileName& fName,
    const Triangulation& t,
    const indexedVertexEnum::vertexType startPointType,
    const indexedVertexEnum::vertexType endPointType
)
{
    OFstream str(fName);

    Pout<< nl
        << "Writing points of types:" << nl;

    forAllConstIter
    (
        HashTable<int>,
        indexedVertexEnum::vertexTypeNames_,
        iter
    )
    {
        if (iter() >= startPointType && iter() <= endPointType)
        {
            Pout<< "    " << iter.key() << nl;
        }
    }

    Pout<< "to " << str.name() << endl;

    for
    (
        typename Triangulation::Finite_vertices_iterator vit =
            t.finite_vertices_begin();
        vit != t.finite_vertices_end();
        ++vit
    )
    {
        if (vit->type() >= startPointType && vit->type() <= endPointType)
        {
            meshTools::writeOBJ(str, topoint(vit->point()));
        }
    }
}
Foam::tmp<Foam::pointField> Foam::DelaunayMeshTools::allPoints
(
    const Triangulation& t
)
{
    tmp<pointField> tpts(new pointField(t.vertexCount(), point::max));
    pointField& pts = tpts.ref();

    for
    (
        typename Triangulation::Finite_vertices_iterator vit =
            t.finite_vertices_begin();
        vit != t.finite_vertices_end();
        ++vit
    )
    {
        if (vit->internalOrBoundaryPoint() && !vit->referred())
        {
            pts[vit->index()] = topoint(vit->point());
        }
    }

    return tpts;
}
bool Foam::conformalVoronoiMesh::distributeBackground(const Triangulation& mesh)
{
    if (!Pstream::parRun())
    {
        return false;
    }

    Info<< nl << "Redistributing points" << endl;

    timeCheck("Before distribute");

    label iteration = 0;

    scalar previousLoadUnbalance = 0;

    while (true)
    {
        scalar maxLoadUnbalance = mesh.calculateLoadUnbalance();

        if
        (
            maxLoadUnbalance <= foamyHexMeshControls().maxLoadUnbalance()
         || maxLoadUnbalance <= previousLoadUnbalance
        )
        {
            // If this is the first iteration, return false, if it was a
            // subsequent one, return true;
            return iteration != 0;
        }

        previousLoadUnbalance = maxLoadUnbalance;

        Info<< "    Total number of vertices before redistribution "
            << returnReduce(label(mesh.number_of_vertices()), sumOp<label>())
            << endl;

        const fvMesh& bMesh = decomposition_().mesh();

        volScalarField cellWeights
        (
            IOobject
            (
                "cellWeights",
                bMesh.time().timeName(),
                bMesh,
                IOobject::NO_READ,
                IOobject::NO_WRITE
            ),
            bMesh,
            dimensionedScalar("weight", dimless, 1e-2),
            zeroGradientFvPatchScalarField::typeName
        );

        meshSearch cellSearch(bMesh, polyMesh::FACE_PLANES);

        labelList cellVertices(bMesh.nCells(), label(0));

        for
        (
            typename Triangulation::Finite_vertices_iterator vit
                = mesh.finite_vertices_begin();
            vit != mesh.finite_vertices_end();
            ++vit
        )
        {
            // Only store real vertices that are not feature vertices
            if (vit->real() && !vit->featurePoint())
            {
                pointFromPoint v = topoint(vit->point());

                label cellI = cellSearch.findCell(v);

                if (cellI == -1)
                {
//                     Pout<< "findCell conformalVoronoiMesh::distribute "
//                         << "findCell "
//                         << vit->type() << " "
//                         << vit->index() << " "
//                         << v << " "
//                         << cellI
//                         << " find nearest cellI ";

                    cellI = cellSearch.findNearestCell(v);
                }

                cellVertices[cellI]++;
            }
        }

        forAll(cellVertices, cI)
        {
            // Give a small but finite weight for empty cells.  Some
            // decomposition methods have difficulty with integer overflows in
            // the sum of the normalised weight field.
            cellWeights.internalField()[cI] = max
            (
                cellVertices[cI],
                1e-2
            );
        }

        autoPtr<mapDistributePolyMesh> mapDist = decomposition_().distribute
        (
            cellWeights
        );

        cellShapeControl_.shapeControlMesh().distribute(decomposition_);

        distribute();

        timeCheck("After distribute");

        iteration++;
    }