Exemple #1
0
        public EdgeTemp SetNode(int volume, int hash, NodeTemp value)
        {
            EdgeTemp connection = this[volume, hash];

            connection.connection = value;
            return(connection);
        }
Exemple #2
0
        /// <summary>
        /// create new edge if it not exist
        /// </summary>
        public EdgeTemp this[int volume, int hash] {
            get {
                VectorInt.Vector2Int key = new VectorInt.Vector2Int(volume, hash);
                EdgeTemp             result;

                if (edges.TryGetValue(key, out result) == false)
                {
                    result = new EdgeTemp(this, volume, hash);
                    result.SetFlag(EdgeTempFlags.Directed, true);
                    edges[key] = result;
                }

                return(result);
            }
            set { edges[new VectorInt.Vector2Int(volume, hash)] = value; }
        }
Exemple #3
0
        public void CreateWithMatlab()
        {
            // ================================
            // generate voronoi graph in matlab
            // ================================


            int J = this.DelaunayVertices.NoOfRows;
            int D = this.DelaunayVertices.NoOfCols;

            if (D != 2)
            {
                throw new NotSupportedException("todo");
            }


            int[][] OutputVertexIndex = new int[J * 5][];
            MultidimensionalArray VertexCoordinates;
            {
                var Matlab = new BatchmodeConnector();

                Matlab.PutMatrix(this.DelaunayVertices, "X");

                // create mirror points
                Matlab.Cmd("[J, D] = size(X);");
                Matlab.Cmd("Xneg = [-X(:, 1), X(:, 2)];");
                Matlab.Cmd("Yneg = [X(:, 1), -X(:, 2)];");
                Matlab.Cmd("X2 = [ones(J, 1) * 2, zeros(J, 1)];");
                Matlab.Cmd("Y2 = [zeros(J, 1), ones(J, 1) * 2];");

                Matlab.Cmd("Xm = X;");
                Matlab.Cmd("Xm = [Xm; Xneg];    % mirror at x = 0");
                Matlab.Cmd("Xm = [Xm; X2 + Xneg]; % mirror at x = 1");
                Matlab.Cmd("Xm = [Xm; Yneg];    % mirror at x = 0");
                Matlab.Cmd("Xm = [Xm; Y2 + Yneg]; % mirror at x = 1");

                // compute Voronoi diagramm
                Matlab.Cmd("[V, C] = voronoin(Xm);");

                // output (export from matlab)
                Matlab.GetStaggeredIntArray(OutputVertexIndex, "C");
                Matlab.GetMatrix(null, "V");

                // run matlab
                Matlab.Execute(false);

                // import here
                VertexCoordinates = (MultidimensionalArray)(Matlab.OutputObjects["V"]);

                // correct indices (1-based index to 0-based index)
                foreach (int[] cell in OutputVertexIndex)
                {
                    int K = cell.Length;
                    for (int k = 0; k < K; k++)
                    {
                        cell[k]--;
                    }
                }
            }

            // ===============
            // record internal
            // ===============

            {
                // define Cell data
                {
                    this.m_CellData         = new CellData();
                    this.m_CellData.m_Owner = this;
                    this.m_VertexData       = new VertexData();
                    this.m_LogEdges         = new LogEdgeData();

                    this.m_VertexData.Coordinates = VertexCoordinates;
                    this.m_CellData.CellVertices  = OutputVertexIndex.GetSubVector(0, J);

                    this.m_CellData.InfoFlags = new CellInfo[J];
                    ArrayTools.SetAll(this.m_CellData.InfoFlags, CellInfo.CellIsAffineLinear | CellInfo.IsAggregate);
                }

                // decomposition of Voronoi cells to triangles/tetrahedrons
                {
                    m_CellData.AggregateCellToParts = new int[J][];
                    if (D == 2)
                    {
                        var Tri = RefElements.Triangle.Instance;
                        m_CellData.RefElements = new RefElement[] { Tri };

                        int cnt = 0;
                        for (int j = 0; j < J; j++)
                        {
                            int[] VtxIndices = m_CellData.CellVertices[j];

                            int[] PartIdx = new int[VtxIndices.Length - 2];
                            for (int i = 0; i < PartIdx.Length; i++)
                            {
                                PartIdx[i] = cnt;
                                cnt++;
                            }
                            m_CellData.AggregateCellToParts[j] = PartIdx;
                        }

                        int NoOfParts = cnt;
                        m_CellData.PartTransformation = MultidimensionalArray.Create(NoOfParts, D, D);
                        m_CellData.PartCenter         = MultidimensionalArray.Create(NoOfParts, D);

                        MultidimensionalArray TriangleVtx = MultidimensionalArray.Create(3, D);
                        for (int j = 0; j < J; j++)
                        {
                            int[] VtxIndices = m_CellData.CellVertices[j];
                            int[] PartIdx    = m_CellData.AggregateCellToParts[j];

                            for (int i = 0; i < PartIdx.Length; i++)
                            {
                                int iV0 = VtxIndices[0];
                                int iV1 = VtxIndices[i + 1];
                                int iV2 = VtxIndices[i + 2];

                                TriangleVtx[0, 0] = m_VertexData.Coordinates[iV0, 0];
                                TriangleVtx[0, 1] = m_VertexData.Coordinates[iV0, 1];
                                TriangleVtx[1, 0] = m_VertexData.Coordinates[iV1, 0];
                                TriangleVtx[1, 1] = m_VertexData.Coordinates[iV1, 1];
                                TriangleVtx[2, 0] = m_VertexData.Coordinates[iV2, 0];
                                TriangleVtx[2, 1] = m_VertexData.Coordinates[iV2, 1];

                                var TR = AffineTrafo.FromPoints(Tri.Vertices, TriangleVtx);

                                m_CellData.PartTransformation.ExtractSubArrayShallow(PartIdx[i], -1, -1).Set(TR.Matrix);
                                m_CellData.PartCenter.ExtractSubArrayShallow(PartIdx[i], -1).SetVector(TR.Affine);
                            }
                        }
                    }
                    else if (D == 3)
                    {
                        throw new NotImplementedException("todo");
                    }
                    else
                    {
                        throw new NotSupportedException("Unknown spatial dimension.");
                    }
                }

                // bounding boxes, transformations
                {
                    BoundingBox BB = new BoundingBox(D);
                    m_CellData.BoundingBoxTransformation = MultidimensionalArray.Create(J, D, D);
                    m_CellData.BoundingBoxCenter         = MultidimensionalArray.Create(J, D);
                    for (int j = 0; j < J; j++)
                    {
                        m_CellData.GetCellBoundingBox(j, BB);
                        for (int d = 0; d < D; d++)
                        {
                            double lo = BB.Min[d];
                            double hi = BB.Max[d];
                            m_CellData.BoundingBoxCenter[j, d]            = 0.5 * (lo + hi);
                            m_CellData.BoundingBoxTransformation[j, d, d] = 0.5 * (hi - lo);
                        }
                    }
                }

                // mapping: vertex to cell
                {
                    List <int>[] VertexToCell = new List <int> [VertexCoordinates.Length];
                    for (int j = 0; j < J; j++)
                    {
                        foreach (int iVtx in OutputVertexIndex[j])
                        {
                            if (VertexToCell[iVtx] == null)
                            {
                                VertexToCell[iVtx] = new List <int>();
                            }

                            if (!VertexToCell[iVtx].Contains(j))
                            {
                                VertexToCell[iVtx].Add(j);
                            }
                        }
                    }

                    m_VertexData.VerticeToCell = new int[VertexToCell.Length][];
                    for (int i = 0; i < VertexToCell.Length; i++)
                    {
                        if (VertexToCell[i] == null)
                        {
                            m_VertexData.VerticeToCell[i] = new int[0];
                        }
                        else
                        {
                            m_VertexData.VerticeToCell[i] = VertexToCell[i].ToArray();
                        }
                    }
                    VertexToCell = null;
                }

                // cell neighbors, edges
                {
                    m_CellData.CellNeighbours = new int[J][];
                    var tmpCells2Edges = new List <int> [J];

                    Dictionary <int, int> ShareCount = new Dictionary <int, int>(); // key: cell index; value: number of vertices shared with this cell
                    var        EdgesTemp             = new List <EdgeTemp>();
                    List <int> Neighs            = new List <int>();
                    List <int> EdgeVtx           = new List <int>();
                    List <int> IdedEdgsAtOneCell = new List <int>();
                    for (int jCell = 0; jCell < J; jCell++)   // loop over cells
                    {
                        ShareCount.Clear();
                        Neighs.Clear();
                        IdedEdgsAtOneCell.Clear();

                        // determine how many vertices 'jCell' shares with other cells
                        foreach (int iVtx in m_CellData.CellVertices[jCell])
                        {
                            foreach (int jOtherCell in m_VertexData.VerticeToCell[iVtx])
                            {
                                if (jOtherCell != jCell)
                                {
                                    if (!ShareCount.ContainsKey(jOtherCell))
                                    {
                                        ShareCount.Add(jOtherCell, 1);
                                    }
                                    else
                                    {
                                        ShareCount[jOtherCell]++;
                                    }
                                }
                            }
                        }

                        // find faces
                        int[][] FaceIdx = ConvexHullFaces(m_VertexData.Coordinates, m_CellData.CellVertices[jCell]);

                        // determine cell neighbors and edges
                        int NoOfFacesFound = 0;
                        foreach (var kv in ShareCount)
                        {
                            int jCellNeigh    = kv.Key;
                            int NoOfSharedVtx = kv.Value;
                            if (NoOfSharedVtx >= D)
                            {
                                // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                                // cells 'jCell' and 'jCellNeigh' share more than 'D' vertices - this is an edge to another cell,
                                // resp. a face of 'jCell'.
                                // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

                                Debug.Assert(jCellNeigh != jCell);
                                Debug.Assert(!Neighs.Contains(jCellNeigh));
                                Neighs.Add(jCellNeigh);
                                NoOfFacesFound++;

                                EdgeVtx.Clear();
                                foreach (int iVtx in m_CellData.CellVertices[jCell])
                                {
                                    if (Array.IndexOf(m_VertexData.VerticeToCell[iVtx], jCellNeigh) >= 0)
                                    {
                                        EdgeVtx.Add(iVtx);
                                    }
                                }


                                if (jCell < jCellNeigh)
                                {
                                    // the pairing 'jCell'/'jCellNeigh' will be discovered twice;
                                    // we only want to record once

                                    var Etmp = new EdgeTemp()
                                    {
                                        jCell1   = jCell,
                                        jCell2   = jCellNeigh,
                                        Vertices = EdgeVtx.ToArray()
                                    };
                                    EdgesTemp.Add(Etmp);
                                    IdedEdgsAtOneCell.Add(EdgesTemp.Count - 1);
                                    if (tmpCells2Edges[jCell] == null)
                                    {
                                        tmpCells2Edges[jCell] = new List <int>();
                                    }
                                    if (tmpCells2Edges[jCellNeigh] == null)
                                    {
                                        tmpCells2Edges[jCellNeigh] = new List <int>();
                                    }
                                    tmpCells2Edges[jCell].Add(EdgesTemp.Count);       // the funky convention for edges-to-cell: the index is
                                    tmpCells2Edges[jCellNeigh].Add(-EdgesTemp.Count); // shifted by 1, out-cell is negative
                                }
                                else
                                {
                                    Debug.Assert(jCellNeigh < jCell);

                                    int MatchCount = 0;
                                    foreach (int i in tmpCells2Edges[jCellNeigh])
                                    {
                                        int iEdge = Math.Abs(i) - 1;

                                        if (EdgesTemp[iEdge].jCell1 == jCellNeigh && EdgesTemp[iEdge].jCell2 == jCell)
                                        {
                                            MatchCount++;
                                            IdedEdgsAtOneCell.Add(iEdge);
                                        }
                                    }
                                    Debug.Assert(MatchCount == 1);
                                }
#if DEBUG
                                if (D == 2)
                                {
                                    Debug.Assert(EdgeVtx.Count == 2);
                                }
                                else if (D == 3)
                                {
                                    // verify that all vertices of the edge are geometrically in one plane

                                    Debug.Assert(EdgeVtx.Count >= 3);
                                    var FacePlane = AffineManifold.FromPoints(
                                        m_VertexData.Coordinates.GetRowPt(EdgeVtx[0]),
                                        m_VertexData.Coordinates.GetRowPt(EdgeVtx[1]),
                                        m_VertexData.Coordinates.GetRowPt(EdgeVtx[2])
                                        );

                                    BoundingBox BB = new BoundingBox(D);
                                    m_CellData.GetCellBoundingBox(jCell, BB);
                                    double h = BB.Diameter;

                                    foreach (int iVtx in EdgeVtx)
                                    {
                                        double dist = Math.Abs(FacePlane.PointDistance(m_VertexData.Coordinates.GetRow(iVtx)));
                                        Debug.Assert(dist < h * 1e-8);
                                    }
                                }
                                else
                                {
                                    throw new NotSupportedException("Unknown spatial dimension.");
                                }
#endif
                            }
                        }
                        m_CellData.CellNeighbours[jCell] = Neighs.ToArray();
                        Debug.Assert(NoOfFacesFound <= FaceIdx.Length);
                        Debug.Assert(NoOfFacesFound == IdedEdgsAtOneCell.Count);

                        // boundary edges
                        if (NoOfFacesFound == FaceIdx.Length)
                        {
                            // nothing to do - all faces/edges identified
#if DEBUG
                            for (int i = 0; i < NoOfFacesFound; i++)
                            {
                                int Matches = 0;
                                for (int l = 0; l < NoOfFacesFound; l++)
                                {
                                    if (FaceIdx[i].SetEquals(EdgesTemp[IdedEdgsAtOneCell[l]].Vertices))
                                    {
                                        Matches++;
                                    }
                                }
                                Debug.Assert(Matches == 1);
                            }
#endif
                        }
                        else
                        {
                            // missing boundary

                            for (int i = 0; i < FaceIdx.Length; i++)
                            {
                                int Matches = 0;
                                for (int l = 0; l < NoOfFacesFound; l++)
                                {
                                    if (FaceIdx[i].SetEquals(EdgesTemp[IdedEdgsAtOneCell[l]].Vertices))
                                    {
                                        Matches++;
                                    }
                                }
                                Debug.Assert(Matches <= 1);

                                if (Matches == 0)
                                {
                                    // boundary edge found
                                    var Etmp = new EdgeTemp()
                                    {
                                        jCell1   = jCell,
                                        jCell2   = int.MinValue,
                                        Vertices = EdgeVtx.ToArray()
                                    };
                                    EdgesTemp.Add(Etmp);
                                    tmpCells2Edges[jCell].Add(EdgesTemp.Count); // index shifted by 1
                                }
                            }
                        }
                    }

                    // convert temporary data structures to the final ones
                    m_CellData.Cells2Edges = new int[J][];
                    var C2E = m_CellData.Cells2Edges;
                    for (int j = 0; j < J; j++)
                    {
                        C2E[j] = tmpCells2Edges[j] != null ? tmpCells2Edges[j].ToArray() : new int[0];
                    }


                    m_GeomEdges = new GeomEdgeData();
                    int NoOfEdges = EdgesTemp.Count;
                    m_GeomEdges.Info          = new EdgeInfo[NoOfEdges];
                    m_LogEdges.CellIndices    = new int[NoOfEdges, 2];
                    m_GeomEdges.VertexIndices = new int[NoOfEdges][];
                    var Evtx = m_GeomEdges.VertexIndices;
                    var E2C  = m_LogEdges.CellIndices;
                    var Einf = m_GeomEdges.Info;
                    for (int iEdge = 0; iEdge < NoOfEdges; iEdge++)
                    {
                        var Etmp = EdgesTemp[iEdge];
                        E2C[iEdge, 0] = Etmp.jCell1;
                        E2C[iEdge, 1] = Etmp.jCell2;
                        Einf[iEdge]   = EdgeInfo.EdgeIsAffineLinear | EdgeInfo.IsAggregate;
                        if (Etmp.jCell2 < 0)
                        {
                            Einf[iEdge] |= EdgeInfo.Boundary;
                        }
                        Evtx[iEdge] = Etmp.Vertices;
                    }
                }


                // edge metrics
                {
                    if (D == 2)
                    {
                        m_GeomEdges.EdgeRefElements = new RefElement[] { Line.Instance };
                    }
                    else if (D == 3)
                    {
                        m_GeomEdges.EdgeRefElements = new RefElement[] { Triangle.Instance };
                    }
                    else
                    {
                        throw new NotSupportedException("Unknown spatial dimension.");
                    }

                    int[][] Evtx = m_GeomEdges.VertexIndices;

                    int NoOfParts = 0;
                    int NoOfEdges = m_GeomEdges.Count;
                    for (int iEdge = 0; iEdge < NoOfEdges; iEdge++)
                    {
                        NoOfParts += Evtx[iEdge].Length - D + 1;
                    }
                    Debug.Assert(D != 2 || NoOfParts == NoOfEdges);

                    m_GeomEdges.Edge2CellTrafoIndex = new int[NoOfParts, 2];
                    var tmpEdg2CellTrafo = new Dictionary <int, Tuple <int, AffineTrafo> >();

                    // unsolved problem:
                    // (D-1) -- dimensional tesselation of edge is given by D -- dimensional tesselation of adjacent cells
                    // * case D == 2: trivial
                    // * case D == 3: the problem is that two adjacent cells will induce _two different_ tesselations, which
                    //                wont match in the general case.


                    MultidimensionalArray PreImage = m_GeomEdges.EdgeRefElements[0].Vertices;
                    MultidimensionalArray Image    = MultidimensionalArray.Create(PreImage.NoOfRows, D);

                    //for(int iEdge )
                }
            }
        }