Monday, 20 November 2017

Adjacency of Pixels

private static int[] GenerateAdjacency(Vector3[] positions,
        List<int> positionIndices)
    {
        // faces within mesh
        int ncFaces = positionIndices.Count / 3;

        // vertex count
        int ncVertices = positions.Length;

        // inst. adjacency array and set all values to -1
        int[] adjacency = Enumerable.Repeat(-1, 3 * ncFaces).ToArray();
        if (adjacency == null)
            throw new OutOfMemoryException("Failed to allocate memory for adjacency data");

        // the edge map will hold an edge center position as key and a list of edges that share the edge center position
        Dictionary<Vector3, List<AdjEdge>> edgeMap = new Dictionary<Vector3, List<AdjEdge>>();

        // edge center position
        Vector3 edgeVector = new Vector3();

        // iterate over list of position indices
        // there are 3 indices per face
        for (int i = 0; i < positionIndices.Count; i+=3)
        {
            // face index
            int iFace = i / 3;

            // compute edge center position
            edgeVector = Quantize((positions[positionIndices[i + 0]] + positions[positionIndices[i + 1]]) / 2);

            // if the edge center doesn't exist in the map then add a new entry
            if (!edgeMap.ContainsKey(edgeVector))
                edgeMap.Add(edgeVector, new List<AdjEdge>());                   

            // add the edge
            edgeMap[edgeVector].Add(
                new AdjEdge(positions[positionIndices[i + 0]], positions[positionIndices[i + 1]], edgeVector, 0, iFace));

            // compute edge center position
            edgeVector = Quantize((positions[positionIndices[i + 1]] + positions[positionIndices[i + 2]]) / 2);

            // if the edge center doesn't exist in the map then add a new entry
            if (!edgeMap.ContainsKey(edgeVector))
                edgeMap.Add(edgeVector, new List<AdjEdge>());

            // add the edge
            edgeMap[edgeVector].Add(
                new AdjEdge(positions[positionIndices[i + 1]], positions[positionIndices[i + 2]], edgeVector, 1, iFace));

            // compute edge center position
            edgeVector = Quantize((positions[positionIndices[i + 2]] + positions[positionIndices[i + 0]]) / 2);

            // if the edge center doesn't exist in the map then add a new entry
            if (!edgeMap.ContainsKey(edgeVector))
                edgeMap.Add(edgeVector, new List<AdjEdge>());

            // add the edge
            edgeMap[edgeVector].Add(
                new AdjEdge(positions[positionIndices[i + 2]], positions[positionIndices[i + 0]], edgeVector, 2, iFace));
        }

        // iterate over the edge map
        foreach (Vector3 key in edgeMap.Keys)
        {
            // list of edges sharing the same center position
            List<AdjEdge> edges = edgeMap[key];

            // iterate over source edges
            for (int i = 0; i < edges.Count - 1; ++i)
            {
                // source edge
                AdjEdge edgeA = edges[i];

                // do not parse edge twice
                if (edgeA._parsed)
                    continue;

                // iterate over comparison edges
                for (int j = i + 1; j < edges.Count; ++j)
                {
                    // comparison edge
                    AdjEdge edgeB = edges[j];

                    // do not parse edge twice
                    if (edgeB._parsed)
                        continue;

                    // compare the edges
                    if (CompareVectors(edgeA._ref0, edgeB._ref1)
                        && CompareVectors(edgeA._ref1, edgeB._ref0))
                    {
                        // the edges were similar so set adjacency for both edges
                        adjacency[3 * edgeA._face + edgeA._edge] = edgeB._face;
                        adjacency[3 * edgeB._face + edgeB._edge] = edgeA._face;

                        // set parsed state true
                        edgeA._parsed = true;
                        edgeB._parsed = true;

                        // break out of comparison loop
                        break;
                    }
                }
            }
        }
        return adjacency;
    }

public struct AdjEdge
        {
            public Vector3 _ref0;
            public Vector3 _ref1;
            public int _edge;
            public int _face;
            public bool _parsed;

            public AdjEdge(Vector3 ref0, Vector3 ref1, int edge, int face)
            {
                _ref0 = ref0;
                _ref1 = ref1;
                _edge = edge;
                _face = face;
                _parsed = false;
            }
        }

private static int[] GenerateAdjacency(Vector3[] positions,
            List<int> positionIndices)
        {
            int ncFaces = positionIndices.Count / 3;
            int ncVertices = positions.Length;

            // inst. adjacency array and set all values to -1
            int[] adjacency = Enumerable.Repeat(-1, 3 * ncFaces).ToArray();
            if (adjacency == null)
                throw new OutOfMemoryException("Failed to allocate memory for adjacency data");

            List<AdjEdge> edges = new List<AdjEdge>();

            for (int i = 0; i < positionIndices.Count; i+=3)
            {
                int iFace = i / 3;
                edges.Add(new AdjEdge(positions[positionIndices[i + 0]], positions[positionIndices[i + 1]], 0, iFace));
                edges.Add(new AdjEdge(positions[positionIndices[i + 1]], positions[positionIndices[i + 2]], 1, iFace));
                edges.Add(new AdjEdge(positions[positionIndices[i + 2]], positions[positionIndices[i + 0]], 2, iFace));
            }

            for (int i = 0; i < edges.Count - 1; ++i)
            {
                AdjEdge edgeA = edges[i];
                if (edgeA._parsed)
                    continue;

                for (int j = 3 - (i % 3) + i; j < edges.Count; ++j)
                {
                    AdjEdge edgeB = edges[j];
                    if (edgeB._parsed)
                        continue;
                    // CompareVectors() returns true if the vectors are separated by a distance less than 1e-6f
                    if (CompareVectors(edgeA._ref0, edgeB._ref1)
                        && CompareVectors(edgeA._ref1, edgeB._ref0))
                    {
                        adjacency[3 * edgeA._face + edgeA._edge] = edgeB._face;
                        adjacency[3 * edgeB._face + edgeB._edge] = edgeA._face;
                        edgeA._parsed = true;
                        edgeB._parsed = true;
                        break;
                    }
                }
            }


            return adjacency;
        }

No comments:

Post a Comment