Beispiel #1
0
        public static void Triangulate(ITriangulatable t, TriangulationAlgorithm algorithm = DEFAULT_ALGORITHM)
        {
            TriangulationContext tcx = CreateContext(algorithm);

            tcx.PrepareTriangulation(t);
            Triangulate(tcx);
        }
        public static void Triangulate(TriangulationAlgorithm algorithm, ITriangulatable t)
        {
            TriangulationContext tcx;

            tcx = CreateContext (algorithm);
            tcx.PrepareTriangulation (t);
            Triangulate (tcx);
        }
Beispiel #3
0
        public static void Triangulate(TriangulationAlgorithm algorithm, ITriangulatable t)
        {
            TriangulationContext tcx;

            tcx = CreateContext(algorithm);
            tcx.PrepareTriangulation(t);
            Triangulate(tcx);
        }
Beispiel #4
0
        public static void Triangulate(TriangulationAlgorithm algorithm, ITriangulatable t)
        {
            //System.Console.WriteLine("Triangulating " + t.FileName);
            //        long time = System.nanoTime();
            var tcx = CreateContext(algorithm);

            tcx.PrepareTriangulation(t);
            Triangulate(tcx);
            //logger.info( "Triangulation of {} points [{}ms]", tcx.getPoints().size(), ( System.nanoTime() - time ) / 1e6 );
        }
Beispiel #5
0
        public static void Triangulate(TriangulationAlgorithm algorithm, ITriangulatable t)
        {
            TriangulationContext tcx;

            System.Console.WriteLine("Triangulating " + t.FileName);
            //        long time = System.nanoTime();
            tcx = CreateContext(algorithm);
            tcx.PrepareTriangulation(t);
            Triangulate(tcx);
            //        logger.info( "Triangulation of {} points [{}ms]", tcx.getPoints().size(), ( System.nanoTime() - time ) / 1e6 );
        }
Beispiel #6
0
        public static void triangulate(TriangulationAlgorithm algorithm,
                                       ITriangulatable t)
        {
            TriangulationContext tcx;

            //        long time = System.nanoTime();
            tcx = createContext(algorithm);
            tcx.prepareTriangulation(t);
            triangulate(tcx);
            //        logger.info( "Triangulation of {} points [{}ms]", tcx.getPoints().Count, ( System.nanoTime() - time ) / 1e6 );
        }
Beispiel #7
0
        /// <summary>
        ///     Prepares the triangulation using the specified t
        /// </summary>
        /// <param name="t">The </param>
        public override void PrepareTriangulation(ITriangulatable t)
        {
            base.PrepareTriangulation(t);

            double xmin;
            double ymin;

            double xmax = xmin = Points[0].X;
            double ymax = ymin = Points[0].Y;

            // Calculate bounds. Should be combined with the sorting
            foreach (TriangulationPoint p in Points)
            {
                if (p.X > xmax)
                {
                    xmax = p.X;
                }

                if (p.X < xmin)
                {
                    xmin = p.X;
                }

                if (p.Y > ymax)
                {
                    ymax = p.Y;
                }

                if (p.Y < ymin)
                {
                    ymin = p.Y;
                }
            }

            double             deltaX = Alpha * (xmax - xmin);
            double             deltaY = Alpha * (ymax - ymin);
            TriangulationPoint p1     = new TriangulationPoint(xmax + deltaX, ymin - deltaY);
            TriangulationPoint p2     = new TriangulationPoint(xmin - deltaX, ymin - deltaY);

            Head = p1;
            Tail = p2;

            //        long time = System.nanoTime();
            // Sort the points along y-axis
            Points.Sort(comparator);

            //        logger.info( "Triangulation setup [{}ms]", ( System.nanoTime() - time ) / 1e6 );
        }
        public override void PrepareTriangulation(ITriangulatable t)
        {
            base.PrepareTriangulation(t);

            double xmax, xmin;
            double ymax, ymin;

            xmax = xmin = Points[0].X;
            ymax = ymin = Points[0].Y;

            TriangulationPoint p;

            for (int i = 0; i < Points.Count; i++)
            {
                p = Points[i];

                if (p.X > xmax)
                {
                    xmax = p.X;
                }

                if (p.X < xmin)
                {
                    xmin = p.X;
                }

                if (p.Y > ymax)
                {
                    ymax = p.Y;
                }

                if (p.Y < ymin)
                {
                    ymin = p.Y;
                }
            }

            double             deltaX = ALPHA * (xmax - xmin);
            double             deltaY = ALPHA * (ymax - ymin);
            TriangulationPoint p1     = new TriangulationPoint(xmax + deltaX, ymin - deltaY);
            TriangulationPoint p2     = new TriangulationPoint(xmin - deltaX, ymin - deltaY);

            Head = p1;
            Tail = p2;

            Points.Sort(_comparator);
        }
Beispiel #9
0
        public override void prepareTriangulation(ITriangulatable t)
        {
            base.prepareTriangulation(t);

            double xmax, xmin;
            double ymax, ymin;

            xmax = xmin = _points[0].getX();
            ymax = ymin = _points[0].getY();
            // Calculate bounds. Should be combined with the sorting
            foreach (TriangulationPoint p in _points)
            {
                if (p.getX() > xmax)
                {
                    xmax = p.getX();
                }
                if (p.getX() < xmin)
                {
                    xmin = p.getX();
                }
                if (p.getY() > ymax)
                {
                    ymax = p.getY();
                }
                if (p.getY() < ymin)
                {
                    ymin = p.getY();
                }
            }

            double deltaX = ALPHA * (xmax - xmin);
            double deltaY = ALPHA * (ymax - ymin);
            TPoint p1     = new TPoint(xmax + deltaX, ymin - deltaY);
            TPoint p2     = new TPoint(xmin - deltaX, ymin - deltaY);

            setHead(p1);
            setTail(p2);

            //        long time = System.nanoTime();
            // Sort the points along y-axis
            _points.Sort(_comparator);

            //Collections.sort(_points, _comparator);
            //        logger.info( "Triangulation setup [{}ms]", ( System.nanoTime() - time ) / 1e6 );
        }
Beispiel #10
0
        public static void InitializeHoles(List <Contour> holes, ITriangulatable parent, ConstrainedPointSet cps)
        {
            int numHoles = holes.Count;
            int holeIdx  = 0;

            // pass 1 - remove duplicates
            while (holeIdx < numHoles)
            {
                int hole2Idx = holeIdx + 1;
                while (hole2Idx < numHoles)
                {
                    bool bSamePolygon = PolygonUtil.PolygonsAreSame2D(holes[holeIdx], holes[hole2Idx]);
                    if (bSamePolygon)
                    {
                        // remove one of them
                        holes.RemoveAt(hole2Idx);
                        --numHoles;
                    }
                    else
                    {
                        ++hole2Idx;
                    }
                }
                ++holeIdx;
            }

            // pass 2: Intersections and Containment
            holeIdx = 0;
            while (holeIdx < numHoles)
            {
                bool bIncrementHoleIdx = true;
                int  hole2Idx          = holeIdx + 1;
                while (hole2Idx < numHoles)
                {
                    if (PolygonUtil.PolygonContainsPolygon(holes[holeIdx], holes[holeIdx].Bounds, holes[hole2Idx], holes[hole2Idx].Bounds, false))
                    {
                        holes[holeIdx].AddHole(holes[hole2Idx]);
                        holes.RemoveAt(hole2Idx);
                        --numHoles;
                    }
                    else if (PolygonUtil.PolygonContainsPolygon(holes[hole2Idx], holes[hole2Idx].Bounds, holes[holeIdx], holes[holeIdx].Bounds, false))
                    {
                        holes[hole2Idx].AddHole(holes[holeIdx]);
                        holes.RemoveAt(holeIdx);
                        --numHoles;
                        bIncrementHoleIdx = false;
                        break;
                    }
                    else
                    {
                        bool bIntersect = PolygonUtil.PolygonsIntersect2D(holes[holeIdx], holes[holeIdx].Bounds, holes[hole2Idx], holes[hole2Idx].Bounds);
                        if (bIntersect)
                        {
                            // this is actually an error condition
                            // fix by merging hole1 and hole2 into hole1 (including the holes inside hole2!) and delete hole2
                            // Then, because hole1 is now changed, restart it's check.
                            PolygonOperationContext ctx = new PolygonOperationContext();
                            if (!ctx.Init(PolygonUtil.PolyOperation.Union | PolygonUtil.PolyOperation.Intersect, holes[holeIdx], holes[hole2Idx]))
                            {
                                if (ctx.mError == PolygonUtil.PolyUnionError.Poly1InsidePoly2)
                                {
                                    holes[hole2Idx].AddHole(holes[holeIdx]);
                                    holes.RemoveAt(holeIdx);
                                    --numHoles;
                                    bIncrementHoleIdx = false;
                                    break;
                                }
                                else
                                {
                                    throw new Exception("PolygonOperationContext.Init had an error during initialization");
                                }
                            }
                            PolygonUtil.PolyUnionError pue = PolygonUtil.PolygonOperation(ctx);
                            if (pue == PolygonUtil.PolyUnionError.None)
                            {
                                Point2DList union        = ctx.Union;
                                Point2DList intersection = ctx.Intersect;

                                // create a new contour for the union
                                Contour c = new Contour(parent);
                                c.AddRange(union);
                                c.Name         = "(" + holes[holeIdx].Name + " UNION " + holes[hole2Idx].Name + ")";
                                c.WindingOrder = Point2DList.WindingOrderType.Default;

                                // add children from both of the merged contours
                                int numChildHoles = holes[holeIdx].GetNumHoles();
                                for (int i = 0; i < numChildHoles; ++i)
                                {
                                    c.AddHole(holes[holeIdx].GetHole(i));
                                }
                                numChildHoles = holes[hole2Idx].GetNumHoles();
                                for (int i = 0; i < numChildHoles; ++i)
                                {
                                    c.AddHole(holes[hole2Idx].GetHole(i));
                                }

                                // make sure we preserve the contours of the intersection
                                Contour cInt = new Contour(c);
                                cInt.AddRange(intersection);
                                cInt.Name         = "(" + holes[holeIdx].Name + " INTERSECT " + holes[hole2Idx].Name + ")";
                                cInt.WindingOrder = Point2DList.WindingOrderType.Default;
                                c.AddHole(cInt);

                                // replace the current contour with the merged contour
                                holes[holeIdx] = c;

                                // toss the second contour
                                holes.RemoveAt(hole2Idx);
                                --numHoles;

                                // current hole is "examined", so move to the next one
                                hole2Idx = holeIdx + 1;
                            }
                            else
                            {
                                throw new Exception("PolygonOperation had an error!");
                            }
                        }
                        else
                        {
                            ++hole2Idx;
                        }
                    }
                }
                if (bIncrementHoleIdx)
                {
                    ++holeIdx;
                }
            }

            numHoles = holes.Count;
            holeIdx  = 0;
            while (holeIdx < numHoles)
            {
                int numPoints = holes[holeIdx].Count;
                for (int i = 0; i < numPoints; ++i)
                {
                    int  j = holes[holeIdx].NextIndex(i);
                    uint constraintCode        = TriangulationConstraint.CalculateContraintCode(holes[holeIdx][i], holes[holeIdx][j]);
                    TriangulationConstraint tc = null;
                    if (!cps.TryGetConstraint(constraintCode, out tc))
                    {
                        tc = new TriangulationConstraint(holes[holeIdx][i], holes[holeIdx][j]);
                        cps.AddConstraint(tc);
                    }

                    // replace the points in the holes with valid points
                    if (holes[holeIdx][i].VertexCode == tc.P.VertexCode)
                    {
                        holes[holeIdx][i] = tc.P;
                    }
                    else if (holes[holeIdx][j].VertexCode == tc.P.VertexCode)
                    {
                        holes[holeIdx][j] = tc.P;
                    }
                    if (holes[holeIdx][i].VertexCode == tc.Q.VertexCode)
                    {
                        holes[holeIdx][i] = tc.Q;
                    }
                    else if (holes[holeIdx][j].VertexCode == tc.Q.VertexCode)
                    {
                        holes[holeIdx][j] = tc.Q;
                    }
                }
                ++holeIdx;
            }
        }
Beispiel #11
0
 public Contour(ITriangulatable parent, IList <TriangulationPoint> points, Point2DList.WindingOrderType windingOrder)
 {
     // Currently assumes that input is pre-checked for validity
     mParent = parent;
     AddRange(points, windingOrder);
 }
Beispiel #12
0
 public Contour(ITriangulatable parent)
 {
     mParent = parent;
 }
Beispiel #13
0
        public virtual void PrepareTriangulation(ITriangulatable t)
        {
            Triangulatable = t;
            TriangulationMode = t.TriangulationMode;
            t.Prepare(this);

            //List<TriangulationConstraint> constraints = new List<TriangulationConstraint>();

            //Console.WriteLine("Points for " + t.FileName + ":");
            //Console.WriteLine("Idx,X,Y,VC,Edges");
            //int numPoints = Points.Count;
            //for (int i = 0; i < numPoints; ++i)
            //{
            //    StringBuilder sb = new StringBuilder(128);
            //    sb.Append(i.ToString());
            //    sb.Append(",");
            //    sb.Append(Points[i].X.ToString());
            //    sb.Append(",");
            //    sb.Append(Points[i].Y.ToString());
            //    sb.Append(",");
            //    sb.Append(Points[i].VertexCode.ToString());
            //    int numEdges = (Points[i].Edges != null) ? Points[i].Edges.Count : 0;
            //    for (int j = 0; j < numEdges; ++j)
            //    {
            //        TriangulationConstraint tc = Points[i].Edges[j];
            //        sb.Append(",");
            //        sb.Append(tc.ConstraintCode.ToString());
            //        constraints.Add(tc);
            //    }
            //    Console.WriteLine(sb.ToString());
            //}

            //int idx = 0;
            //Console.WriteLine("Constraints " + t.FileName + ":");
            //Console.WriteLine("EdgeIdx,Px,Py,PVC,Qx,Qy,QVC,ConstraintCode,Owner");
            //foreach (TriangulationConstraint tc in constraints)
            //{
            //    StringBuilder sb = new StringBuilder(128);

            //    sb.Append(idx.ToString());
            //    sb.Append(",");
            //    sb.Append(tc.P.X.ToString());
            //    sb.Append(",");
            //    sb.Append(tc.P.Y.ToString());
            //    sb.Append(",");
            //    sb.Append(tc.P.VertexCode.ToString());
            //    sb.Append(",");
            //    sb.Append(tc.Q.X.ToString());
            //    sb.Append(",");
            //    sb.Append(tc.Q.Y.ToString());
            //    sb.Append(",");
            //    sb.Append(tc.Q.VertexCode.ToString());
            //    sb.Append(",");
            //    sb.Append(tc.ConstraintCode.ToString());
            //    sb.Append(",");
            //    if (tc.Q.HasEdge(tc.P))
            //    {
            //        sb.Append("Q");
            //    }
            //    else
            //    {
            //        sb.Append("P");
            //    }
            //    Console.WriteLine(sb.ToString());

            //    ++idx;
            //}
        }
Beispiel #14
0
 public virtual void prepareTriangulation(ITriangulatable t)
 {
     _triUnit           = t;
     _triangulationMode = t.getTriangulationMode();
     t.prepareTriangulation(this);
 }
        public override void PrepareTriangulation(ITriangulatable t)
        {
            base.PrepareTriangulation (t);

            double xmax, xmin;
            double ymax, ymin;

            xmax = xmin = Points [0].X;
            ymax = ymin = Points [0].Y;

            // Calculate bounds. Should be combined with the sorting
            foreach (TriangulationPoint p in Points) {
                if (p.X > xmax) {
                    xmax = p.X;
                }
                if (p.X < xmin) {
                    xmin = p.X;
                }
                if (p.Y > ymax) {
                    ymax = p.Y;
                }
                if (p.Y < ymin) {
                    ymin = p.Y;
                }
            }

            double deltaX = ALPHA * (xmax - xmin);
            double deltaY = ALPHA * (ymax - ymin);
            TriangulationPoint p1 = new TriangulationPoint (xmax + deltaX, ymin - deltaY);
            TriangulationPoint p2 = new TriangulationPoint (xmin - deltaX, ymin - deltaY);

            Head = p1;
            Tail = p2;

            //        long time = System.nanoTime();
            // Sort the points along y-axis
            Points.Sort (_comparator);
            //        logger.info( "Triangulation setup [{}ms]", ( System.nanoTime() - time ) / 1e6 );
        }
Beispiel #16
0
        protected override void OnPaint(PaintEventArgs e)
        {
            ITriangulatable t = DisplayObjects[mDisplayIndex];

            Text = "poly2tri test: " + t.FileName;

            float xmin = (float)t.MinX;
            float xmax = (float)t.MaxX;
            float ymin = (float)t.MinY;
            float ymax = (float)t.MaxY;

            var fx = e.Graphics;

            {
                Font textFont = new Font("Times New Roman", 12);
                System.Drawing.Brush textBrush = System.Drawing.Brushes.Black;
                fx.DrawString("space = Pause/Unpause", textFont, textBrush, new PointF(10.0f, 10.0f));
                fx.DrawString("left/right arrow (while paused) = prev/next example", textFont, textBrush, new PointF(10.0f, 30.0f));
                fx.DrawString("mouse wheel = zoom in/out", textFont, textBrush, new PointF(10.0f, 50.0f));
                fx.DrawString("drag = pan", textFont, textBrush, new PointF(10.0f, 70.0f));
                fx.DrawString("double-click = reset zoom/pan", textFont, textBrush, new PointF(10.0f, 90.0f));
            }

            if (mbPaused)
            {
                Font textFont = new Font("Times New Roman", 24);
                System.Drawing.Brush textBrush = System.Drawing.Brushes.Black;
                fx.DrawString("Paused", textFont, textBrush, new PointF((ClientSize.Width / 2.0f) - 20.0f, 10.0f));
            }

            if (xmin < xmax && ymin < ymax)
            {
                float   w            = xmax - xmin;
                float   h            = ymax - ymin;
                Point2D ctr          = new Point2D((double)ClientSize.Width / 2.0, (double)ClientSize.Height / 2.0);
                Point2D screenScaler = new Point2D((double)ClientSize.Width / (double)w, (double)ClientSize.Height / (double)h);
                Point2D zoomPoint    = new Point2D(-mZoomPoint.X, mZoomPoint.Y);
                zoomPoint.RotateDegrees(t.DisplayRotate);
                zoomPoint.Scale(1.0 / screenScaler.X, 1.0 / screenScaler.Y);
                float zoom = mZoomLevel * (float)Math.Min(screenScaler.X, screenScaler.Y);

                fx.TranslateTransform(ctr.Xf, ctr.Yf);
                fx.RotateTransform(t.DisplayRotate);
                fx.ScaleTransform(zoom, -zoom);
                fx.TranslateTransform((-(xmax + xmin) / 2.0f) - zoomPoint.Xf, (-(ymax + ymin) / 2.0f) - zoomPoint.Yf);

                var penConstrained = new Pen(Color.Red, 1.0f / zoom);
                //var penDelaunay = new Pen(Color.Blue, 1.0f / zoom);
                var penNormal     = new Pen(Color.Silver, 1.0f / zoom);
                var penErrorCase1 = new Pen(Color.Purple, 1.0f / zoom);
                var penErrorCase2 = new Pen(Color.Cyan, 1.0f / zoom);
                foreach (var tri in t.Triangles)
                {
                    PointF[] pts = new PointF[]
                    {
                        new PointF(tri.Points[0].Xf, tri.Points[0].Yf),
                        new PointF(tri.Points[1].Xf, tri.Points[1].Yf),
                        new PointF(tri.Points[2].Xf, tri.Points[2].Yf),
                    };
                    for (int i = 0; i < 3; ++i)
                    {
                        if (t.DisplayFlipX)
                        {
                            pts[i].X = xmax - (pts[i].X - xmin);
                        }
                        if (t.DisplayFlipY)
                        {
                            pts[i].Y = ymax - (pts[i].Y - ymin);
                        }
                    }
                    for (int i = 0; i < 3; ++i)
                    {
                        var curPen              = penNormal;
                        DTSweepConstraint edge  = null;
                        bool isConstrained      = tri.GetConstrainedEdgeCCW(tri.Points[i]);
                        bool hasConstrainedEdge = tri.GetEdgeCCW(tri.Points[i], out edge);
                        if (isConstrained || hasConstrainedEdge)
                        {
                            if (isConstrained && hasConstrainedEdge)
                            {
                                curPen = penConstrained;
                            }
                            else if (isConstrained && !hasConstrainedEdge)
                            {
                                // this will happen when edges are split and is expected
                                //curPen = penErrorCase1;
                                curPen = penConstrained;
                            }
                            else
                            {
                                curPen = penErrorCase2;
                            }
                        }
                        //else if (tri.GetDelaunayEdgeCCW(tri.Points[i]))
                        //{
                        //    curPen = penDelaunay;
                        //}
                        fx.DrawLine(curPen, pts[i], pts[(i + 1) % 3]);
                    }
                }
                fx.ResetTransform();

                {
                    Point2D imageMouseCoord = new Point2D(mMouseImageCoord.X, (double)ClientSize.Height - mMouseImageCoord.Y);
                    imageMouseCoord.Subtract(ctr);
                    imageMouseCoord.RotateDegrees(t.DisplayRotate);
                    imageMouseCoord.Scale(1.0 / mZoomLevel);
                    imageMouseCoord.Scale(1.0 / screenScaler.X, 1.0 / screenScaler.Y);
                    imageMouseCoord.Translate((w / 2.0) + zoomPoint.X, (h / 2.0) + zoomPoint.Y);
                    if (t.DisplayFlipX)
                    {
                        imageMouseCoord.X = (double)xmax - (imageMouseCoord.X - (double)xmin);
                    }
                    if (t.DisplayFlipY)
                    {
                        imageMouseCoord.Y = (double)ymax - (imageMouseCoord.Y - (double)ymin);
                    }

                    Font textFont = new Font("Times New Roman", 12);
                    System.Drawing.Brush textBrush = System.Drawing.Brushes.Black;
                    fx.DrawString("Image X: " + imageMouseCoord.X.ToString(), textFont, textBrush, new PointF(20.0f, ClientSize.Height - 40.0f));
                    fx.DrawString("Image Y: " + imageMouseCoord.Y.ToString(), textFont, textBrush, new PointF(20.0f, ClientSize.Height - 20.0f));
                    fx.DrawString("ZoomPoint X: " + zoomPoint.X.ToString(), textFont, textBrush, new PointF(300.0f, ClientSize.Height - 40.0f));
                    fx.DrawString("ZoomPoint Y: " + zoomPoint.Y.ToString(), textFont, textBrush, new PointF(300.0f, ClientSize.Height - 20.0f));
                    fx.DrawString("ZoomLevel: " + mZoomLevel.ToString(), textFont, textBrush, new PointF(ClientSize.Width - 150.0f, ClientSize.Height - 20.0f));

                    //fx.DrawString("MX: " + mMouseImageCoord.X.ToString(), textFont, textBrush, new PointF(600.0f, ClientSize.Height - 40.0f));
                    //fx.DrawString("MY: " + mMouseImageCoord.Y.ToString(), textFont, textBrush, new PointF(600.0f, ClientSize.Height - 20.0f));
                }
            }

            fx.DrawImage(ExampleData.Logo256x256, ClientSize.Width - kImageWidth - 10, 10, kImageWidth, kImageWidth);

            base.OnPaint(e);
        }
 public virtual void PrepareTriangulation(ITriangulatable t)
 {
     Triangulatable = t;
     TriangulationMode = t.TriangulationMode;
     t.Prepare (this);
 }
Beispiel #18
0
 public virtual void PrepareTriangulation(ITriangulatable t)
 {
     Triangulatable    = t;
     TriangulationMode = t.TriangulationMode;
     t.Prepare(this);
 }
        public virtual void PrepareTriangulation(ITriangulatable t)
        {
            Triangulatable    = t;
            TriangulationMode = t.TriangulationMode;
            t.Prepare(this);

            //List<TriangulationConstraint> constraints = new List<TriangulationConstraint>();

            //Console.WriteLine("Points for " + t.FileName + ":");
            //Console.WriteLine("Idx,X,Y,VC,Edges");
            //int numPoints = Points.Count;
            //for (int i = 0; i < numPoints; ++i)
            //{
            //    StringBuilder sb = new StringBuilder(128);
            //    sb.Append(i.ToString());
            //    sb.Append(",");
            //    sb.Append(Points[i].X.ToString());
            //    sb.Append(",");
            //    sb.Append(Points[i].Y.ToString());
            //    sb.Append(",");
            //    sb.Append(Points[i].VertexCode.ToString());
            //    int numEdges = (Points[i].Edges != null) ? Points[i].Edges.Count : 0;
            //    for (int j = 0; j < numEdges; ++j)
            //    {
            //        TriangulationConstraint tc = Points[i].Edges[j];
            //        sb.Append(",");
            //        sb.Append(tc.ConstraintCode.ToString());
            //        constraints.Add(tc);
            //    }
            //    Console.WriteLine(sb.ToString());
            //}

            //int idx = 0;
            //Console.WriteLine("Constraints " + t.FileName + ":");
            //Console.WriteLine("EdgeIdx,Px,Py,PVC,Qx,Qy,QVC,ConstraintCode,Owner");
            //foreach (TriangulationConstraint tc in constraints)
            //{
            //    StringBuilder sb = new StringBuilder(128);

            //    sb.Append(idx.ToString());
            //    sb.Append(",");
            //    sb.Append(tc.P.X.ToString());
            //    sb.Append(",");
            //    sb.Append(tc.P.Y.ToString());
            //    sb.Append(",");
            //    sb.Append(tc.P.VertexCode.ToString());
            //    sb.Append(",");
            //    sb.Append(tc.Q.X.ToString());
            //    sb.Append(",");
            //    sb.Append(tc.Q.Y.ToString());
            //    sb.Append(",");
            //    sb.Append(tc.Q.VertexCode.ToString());
            //    sb.Append(",");
            //    sb.Append(tc.ConstraintCode.ToString());
            //    sb.Append(",");
            //    if (tc.Q.HasEdge(tc.P))
            //    {
            //        sb.Append("Q");
            //    }
            //    else
            //    {
            //        sb.Append("P");
            //    }
            //    Console.WriteLine(sb.ToString());

            //    ++idx;
            //}
        }