private int[] BuildCollapseIndex(List <EdgeRecord> collapseRec)
        {
            int vn = mesh.VertexCount;

            int[] collapseIndex = new int[vn];
            for (int i = 0; i < vn; i++)
            {
                collapseIndex[i] = -1;
            }

            for (int i = collapseRec.Count - 1; i >= 0; i--)
            {
                EdgeRecord rec = collapseRec[i];
                int        s   = rec.vIndex;
                int        t   = rec.minIndex;

                if (collapseIndex[t] == -1)
                {
                    collapseIndex[s] = t;
                }
                else
                {
                    collapseIndex[s] = collapseIndex[t];
                }
            }
            return(collapseIndex);
        }
        private void UpdateEdgeCollapseRecords(PriorityQueue queue, EdgeRecord[] edgeRec, int index)
        {
            Vector3d   u    = new Vector3d(mesh.VertexPos, index * 3);
            EdgeRecord uRec = edgeRec[index];

            uRec.minError = double.MaxValue;
            foreach (int j in uRec.adjV)
            {
                int adjCount = 0;
                foreach (int k in edgeRec[j].adjV)
                {
                    if (uRec.adjV.Contains(k))
                    {
                        adjCount++;
                    }
                }
                if (adjCount != 2)
                {
                    continue;
                }

                Vector3d uv  = u - new Vector3d(mesh.VertexPos, j * 3);
                double   err = uRec.area * uv.Dot(uv);
                if (err < uRec.minError)
                {
                    uRec.minError = err;
                    uRec.minIndex = j;
                }
            }
            queue.Update(uRec);
        }
Пример #3
0
 public override bool Equals(object obj)
 {
     if (obj is EdgeRecord)
     {
         EdgeRecord e = obj as EdgeRecord;
         return((this.p1 == e.p1 && this.p2 == e.p2) ||
                (this.p1 == e.p2 && this.p2 == e.p1));
     }
     return(false);
 }
            public int CompareTo(object obj)
            {
                EdgeRecord rec = obj as EdgeRecord;

                if (minError < rec.minError)
                {
                    return(-1);
                }
                if (minError > rec.minError)
                {
                    return(1);
                }
                return(0);
            }
        private EdgeRecord[] CreateEdgeCollapseRecords()
        {
            int vn = mesh.VertexCount;
            int fn = mesh.FaceCount;

            EdgeRecord[] rec = new EdgeRecord[vn];
            for (int i = 0; i < vn; i++)
            {
                rec[i] = new EdgeRecord(i);
            }

            double[] K = new double[10];
            for (int i = 0, j = 0; i < fn; i++, j += 3)
            {
                int      c1       = mesh.FaceIndex[j];
                int      c2       = mesh.FaceIndex[j + 1];
                int      c3       = mesh.FaceIndex[j + 2];
                Vector3d v1       = new Vector3d(mesh.VertexPos, c1 * 3);
                Vector3d v2       = new Vector3d(mesh.VertexPos, c2 * 3);
                Vector3d v3       = new Vector3d(mesh.VertexPos, c3 * 3);
                double   faceArea = ((v2 - v1).Cross(v3 - v1)).Length() / 2.0;
                rec[c1].area += faceArea;
                rec[c2].area += faceArea;
                rec[c3].area += faceArea;
            }

            for (int i = 0, j = 0; i < vn; i++, j += 3)
            {
                Vector3d   u    = new Vector3d(mesh.VertexPos, j);
                EdgeRecord uRec = rec[i];
                foreach (int k in mesh.AdjVV[i])
                {
                    Vector3d uv  = u - new Vector3d(mesh.VertexPos, k * 3);
                    double   err = uRec.area * uv.Dot(uv);
                    if (err < uRec.minError)
                    {
                        uRec.minError = err;
                        uRec.minIndex = k;
                    }
                    uRec.adjV.Add(k);
                }
            }
            return(rec);
        }
Пример #6
0
        public static void PaintPolygon(this Bitmap bitmap, Polygon polygon, Color color)
        {
            List <EdgeRecord>[] record = new List <EdgeRecord> [bitmap.y + 1];
            for (int i = 0; i < polygon.length; i++)
            {
                Point p1 = polygon[i], p2 = polygon[(i + 1 >= polygon.length)?0:(i + 1)];
                int   y1 = (int)(Math.Ceiling(p1.y));
                int   y2 = (int)(Math.Ceiling(p2.y));
                if (y1 < 0)
                {
                    y1 = 0;
                }
                if (y2 < 0)
                {
                    y2 = 0;
                }
                if (y1 > bitmap.y)
                {
                    y2 = bitmap.y;
                }
                if (y2 > bitmap.y)
                {
                    y2 = bitmap.y;
                }
                if (y1 == y2)
                {
                    continue;
                }
                Point pBegin, pEnd;
                int   yBegin, yEnd;
                if (y1 > y2)
                {
                    pBegin = p2;
                    pEnd   = p1;
                    yBegin = y2;
                    yEnd   = y1;
                }
                else
                {
                    pBegin = p1;
                    pEnd   = p2;
                    yBegin = y1;
                    yEnd   = y2;
                }
                float dx = (pEnd.x - pBegin.x) / (pEnd.y - pBegin.y);
                float x  = (yBegin - pBegin.y) * dx + pBegin.x;
                if (record[yBegin] == null)
                {
                    record[yBegin] = new List <EdgeRecord>();
                }
                record[yBegin].Add(new EdgeRecord {
                    x = x, dx = dx, ymax = yEnd
                });
            }
            List <EdgeRecord> intersect = new List <EdgeRecord>();

            for (int line = 0; line < bitmap.y; line++)
            {
                if (record[line] != null)
                {
                    intersect.AddRange(record[line]);
                }
                intersect.RemoveAll((edge) => edge.ymax <= line);
                intersect.Sort((edge1, edge2) => Comparer <float> .Default.Compare(edge1.x, edge2.x));
                if (intersect.Count % 2 != 0)
                {
                    throw new Exception("Odd edges!");
                }
                for (int i = 0; i < intersect.Count / 2; i++)
                {
                    float left   = intersect[2 * i].x;
                    float right  = intersect[2 * i + 1].x;
                    int   lPoint = (int)(Math.Ceiling(left));
                    int   rPoint = (int)(Math.Floor(right));
                    if (lPoint < 0)
                    {
                        lPoint = 0;
                    }
                    if (rPoint < 0)
                    {
                        lPoint = 0;
                    }
                    if (lPoint > bitmap.x)
                    {
                        lPoint = bitmap.x;
                    }
                    if (rPoint > bitmap.x)
                    {
                        lPoint = bitmap.x;
                    }
                    for (int point = lPoint; point <= rPoint; point++)
                    {
                        bitmap[point, line] = color;
                    }
                }
                for (int i = 0; i < intersect.Count; i++)
                {
                    intersect[i] = new EdgeRecord {
                        x = intersect[i].x + intersect[i].dx, dx = intersect[i].dx, ymax = intersect[i].ymax
                    };
                }
            }
        }
Пример #7
0
        private void MainLoop()
        {
            int count = 0;

            while (faceQueue.Count > 0)
            {
                count++;
                HullFace face = faceQueue.Dequeue();

                if (face.active == false)
                {
                    continue;
                }

                if (face.furthestIndex != -1)
                {
                    int p0 = face.furthestIndex;

                    this.hullVertices.Add(p0);

                    // collect visible faces, boundary edges and assoicated vertices
                    List <HullFace>      holeFace         = new List <HullFace>();
                    HashSet <EdgeRecord> holeBoundary     = new HashSet <EdgeRecord>();
                    HashSet <int>        assoicatedVertex = new HashSet <int>();
                    foreach (HullFace f in this.surfaceSet)
                    {
                        Vector3d v = this.p[p0] - this.p[f.p1];
                        if (v.Dot(f.normal) > 0)
                        {
                            holeFace.Add(f);

                            int        p1 = f.p1;
                            int        p2 = f.p2;
                            int        p3 = f.p3;
                            EdgeRecord r1 = new EdgeRecord(p1, p2);
                            EdgeRecord r2 = new EdgeRecord(p2, p3);
                            EdgeRecord r3 = new EdgeRecord(p3, p1);
                            if (holeBoundary.Contains(r1))
                            {
                                holeBoundary.Remove(r1);
                            }
                            else
                            {
                                holeBoundary.Add(r1);
                            }
                            if (holeBoundary.Contains(r2))
                            {
                                holeBoundary.Remove(r2);
                            }
                            else
                            {
                                holeBoundary.Add(r2);
                            }
                            if (holeBoundary.Contains(r3))
                            {
                                holeBoundary.Remove(r3);
                            }
                            else
                            {
                                holeBoundary.Add(r3);
                            }

                            foreach (int index in f.associatedPoints)
                            {
                                assoicatedVertex.Add(index);
                            }
                        }
                    }
                    if (holeFace.Count == 0)
                    {
                        throw new Exception();
                    }

                    // remove add visible faces
                    foreach (HullFace f in holeFace)
                    {
                        this.surfaceSet.Remove(f);
                        f.active = false;
                    }

                    // add new faces
                    foreach (EdgeRecord edge in holeBoundary)
                    {
                        HullFace newFace = new HullFace(p0, edge.p1, edge.p2);
                        newFace.normal = ((p[edge.p1] - p[p0]).Cross(p[edge.p2] - p[p0])).normalize();
                        this.surfaceSet.Add(newFace);
                        this.faceQueue.Enqueue(newFace);

                        // add assoicated vertices
                        foreach (int index in assoicatedVertex)
                        {
                            if (index == p0)
                            {
                                continue;
                            }

                            double dis = (p[index] - p[p0]).Dot(newFace.normal);
                            if (dis > 0)
                            {
                                newFace.AddPoint(index, dis);
                            }
                        }
                    }
                }
            }
            computeCenter();
        }
        private void Simplify()
        {
            Program.PrintText("Simplification");
            int vn = mesh.VertexCount;
//          if (vn <= targetVertices) return;

            int nextLevel = (int)(vn * simplificationRatio);

            if (nextLevel < targetVertices)
            {
                nextLevel = targetVertices;
            }

            // copy connectivity
            // VertexRecord[] vRec = new VertexRecord[vn];

            EdgeRecord[]      edgeRec     = CreateEdgeCollapseRecords();
            List <EdgeRecord> collapseRec = new List <EdgeRecord>();

            bool[]        collapsed = new bool[vn];
            PriorityQueue queue     = new PriorityQueue(vn);

            for (int i = 0; i < vn; i++)
            {
                queue.Insert(edgeRec[i]);
                collapsed[i] = false;
            }

            {
                Program.PrintText("output mesh level: " + vn);
                List <VertexRecord> vRecList = new List <VertexRecord>();
                for (int j = 0; j < vn; j++)
                {
                    if (collapsed[j])
                    {
                        continue;
                    }
                    VertexRecord r = new VertexRecord(j);
                    foreach (int adj in edgeRec[j].adjV)
                    {
                        r.adjV.Add(adj);
                    }

                    vRecList.Add(r);
                }
                simplifiedMeshes.Add(vRecList);
                collapseRec.Reverse();
                collapsedRecords.Add(collapseRec);
                faceRecords.Add((int[])mesh.FaceIndex.Clone());
                collapseRec = new List <EdgeRecord>();
            }

            int count = vn;

            for (int i = 0; i < vn - targetVertices; i++)
            {
                EdgeRecord rec1 = (EdgeRecord)queue.DeleteMin();
                EdgeRecord rec2 = edgeRec[rec1.minIndex];
                rec2.area += rec1.area;
                collapseRec.Add(rec1);
                collapsed[rec1.vIndex] = true;
                count--;

                foreach (int j in rec1.adjV)
                {
                    edgeRec[j].adjV.Remove(rec1.vIndex);
                    if (j != rec2.vIndex)
                    {
                        edgeRec[j].adjV.Add(rec2.vIndex);
                        edgeRec[rec2.vIndex].adjV.Add(j);
                    }
                }

                foreach (int j in rec2.adjV)
                {
                    UpdateEdgeCollapseRecords(queue, edgeRec, j);
                }
                UpdateEdgeCollapseRecords(queue, edgeRec, rec2.vIndex);

                if (count == nextLevel)
                {
                    Program.PrintText("output mesh level: " + count);
                    List <VertexRecord> vRecList = new List <VertexRecord>();
                    for (int j = 0; j < vn; j++)
                    {
                        if (collapsed[j])
                        {
                            continue;
                        }
                        VertexRecord r = new VertexRecord(j);
                        foreach (int adj in edgeRec[j].adjV)
                        {
                            r.adjV.Add(adj);
                        }

                        vRecList.Add(r);
                    }

                    simplifiedMeshes.Add(vRecList);
                    int[] fr = BuildCollapsedFaceIndex(faceRecords[faceRecords.Count - 1], collapseRec);
                    faceRecords.Add(fr);
                    collapseRec.Reverse();
                    collapsedRecords.Add(collapseRec);
                    collapseRec = new List <EdgeRecord>();

                    nextLevel = (int)(nextLevel * simplificationRatio);
                    if (nextLevel < targetVertices)
                    {
                        nextLevel = targetVertices;
                    }
                }
            }

            simplifiedMeshes.Reverse();
            collapsedRecords.Reverse();
            faceRecords.Reverse();
        }