예제 #1
0
        public static PathDefWithClosed Sanitize(PathDefWithClosed inp)
        {
            PathDefWithClosed R = new PathDefWithClosed();

            R.Width  = inp.Width;
            R.Closed = inp.Closed;

            PointD last = new PointD(double.NaN, double.NaN);

            foreach (var v in inp.Vertices)
            {
                if (v != last)
                {
                    R.Vertices.Add(v);
                    last = v.Copy();
                }
            }
            return(R);
        }
예제 #2
0
        public static List <PathDefWithClosed> LineSegmentsToPolygons(List <PathDefWithClosed> input, bool joinclosest = true)
        {
            // return input;
            List <PathDefWithClosed> Paths         = new List <PathDefWithClosed>();
            List <PathDefWithClosed> FirstSweep    = new List <PathDefWithClosed>();
            List <PathDefWithClosed> LeftoverLines = new List <PathDefWithClosed>();

            if (input.Count == 0)
            {
                return(LeftoverLines);
            }
            try
            {
                foreach (var p in input)
                {
                    if (p.Vertices.Count() > 0)
                    {
                        FirstSweep.Add(Sanitize(p));
                    }
                }
                FirstSweep = StripOverlaps(FirstSweep);


                LeftoverLines.Add(FirstSweep[0]);
                for (int i = 1; i < FirstSweep.Count; i++)
                {
                    var LastLeft  = LeftoverLines.Last();
                    var LastLeftP = LastLeft.Vertices.Last();

                    if (FirstSweep[i].Vertices.First() == LastLeftP)
                    {
                        LastLeft.Vertices.AddRange(FirstSweep[i].Vertices.Skip(1));
                    }
                    else
                    {
                        if (FirstSweep[i].Vertices.Last() == LastLeftP)
                        {
                            FirstSweep[i].Vertices.Reverse();
                            LastLeft.Vertices.AddRange(FirstSweep[i].Vertices.Skip(1));
                        }
                        else
                        {
                            LeftoverLines.Add(FirstSweep[i]);
                        }
                    }
                }
                LeftoverLines = StripOverlaps(LeftoverLines);
            }
            catch (Exception E)
            {
                Console.WriteLine(E.Message);
            }

            while (LeftoverLines.Count > 0)
            {
                bool added = false;

                var a = LeftoverLines.Last();
                LeftoverLines.Remove(a);

                if (added == false)
                {
                    PathDefWithClosed P = new PathDefWithClosed();
                    P.Width = a.Width;

                    foreach (var v in a.Vertices)
                    {
                        P.Vertices.Add(v);
                    }
                    //P.Points.Add(a.Last());
                    if (a.Vertices.First() == a.Vertices.Last())
                    {
                        int matching = 0;
                        for (int i = 0; i < a.Vertices.Count / 2; i++)
                        {
                            if (a.Vertices[i] == a.Vertices[a.Vertices.Count - 1 - i])
                            {
                                matching++;
                            }
                        }
                        if (matching > 1)
                        {
                            P.Vertices.Clear();
                            List <PointD> DebugN  = new List <PointD>();
                            List <int>    Kinks   = new List <int>();
                            List <int>    KinkEnd = new List <int>();

                            Kinks.Add(0);
                            for (int i = 1; i < a.Vertices.Count; i++)
                            {
                                var N1 = MathHelpers.Normal(a.Vertices[(i - 1)], a.Vertices[i]);
                                var N2 = MathHelpers.Normal(a.Vertices[i], a.Vertices[(i + 1) % a.Vertices.Count()]);
                                if (N1.Dot(N2) < 0.8)
                                {
                                    DebugN.Add(a.Vertices[i]);
                                    DebugN.Add(N1 * 4.0 + a.Vertices[i]);
                                    Kinks.Add(i);
                                    KinkEnd.Add(i);
                                }
                            }
                            KinkEnd.Add(a.Vertices.Count - 1);

                            double maxD   = 0;
                            int    maxSeg = 0;
                            for (int i = 0; i < Kinks.Count; i++)
                            {
                                double D = 0;
                                for (int j = Kinks[i]; j < KinkEnd[i]; j++)
                                {
                                    D += (a.Vertices[j] - a.Vertices[j + 1]).Length();
                                }
                                if (D > maxD)
                                {
                                    maxD   = D;
                                    maxSeg = i;
                                }
                            }



                            for (int i = Kinks[maxSeg]; i < KinkEnd[maxSeg]; i++)
                            {
                                P.Vertices.Add(a.Vertices[i]);
                            }

                            bool dumpdebugline = false;
                            if (dumpdebugline)
                            {
                                PolyLineSet.Bounds Bbox = new PolyLineSet.Bounds();

                                foreach (var v in a.Vertices)
                                {
                                    Bbox.FitPoint(v);
                                    Bbox.FitPoint(new PointD(v.X + 10, v.Y + 10));
                                    Bbox.FitPoint(new PointD(v.X - 10, v.Y - 10));
                                }
                                float  Scaler = 50.0f;
                                Bitmap OutB   = new Bitmap((int)(Bbox.Width() * Scaler), (int)(Bbox.Height() * Scaler));

                                Graphics G = Graphics.FromImage(OutB);
                                G.Clear(Color.White);
                                GraphicsGraphicsInterface GGI = new GraphicsGraphicsInterface(G);

                                GGI.TranslateTransform((float)-Bbox.TopLeft.X * Scaler, (float)-Bbox.TopLeft.Y * Scaler);
                                GGI.DrawLines(new Pen(Color.Red, 0.1f), (from i in a.Vertices select(i * Scaler).ToF()).ToArray());
                                for (int i = 1; i < a.Vertices.Count; i++)
                                {
                                    var N = MathHelpers.Normal(a.Vertices[i - 1], a.Vertices[i]);

                                    GGI.DrawString(i.ToString(), new Font("arial", 14), new SolidBrush(Color.FromArgb((i + 128) % 256, i % 256, i % 256)), (float)a.Vertices[i].X * Scaler + (float)N.X * 20.0f, (float)a.Vertices[i].Y * Scaler + (float)N.Y * 20.0f, new StringFormat());
                                }
                                for (int i = 0; i < DebugN.Count; i += 2)
                                {
                                    GGI.DrawLine(new Pen(Color.DarkGreen, 1.0f), (DebugN[i] * Scaler).ToF(), (DebugN[i + 1] * Scaler).ToF());
                                }
                                OutB.Save("testout.png");
                            }
                        }
                        else
                        {
                            a.Vertices.Remove(a.Vertices.Last());
                            //Console.WriteLine("closed path with {0} points during stage 2: {1} reversematched", a.Vertices.Count(), matching);
                            P.Closed = true;
                        }
                    }
                    Paths.Add(P);
                }
            }
            Paths = StripOverlaps(Paths);
            //  return Paths;


            int Merges   = 1;
            int startat  = 0;
            int lasthigh = 0;

            while (Merges > 0)
            {
                startat = lasthigh;
                Merges  = FindNextMerge(Paths, out lasthigh, startat);
            }
            //return Paths;

            int ClosedCount = (from i in Paths where i.Closed == true select i).Count();

            if (ClosedCount < Paths.Count)
            {
                //Console.WriteLine("{0}/{1} paths open - finding closest connections", Paths.Count - ClosedCount, Paths.Count);
                if (joinclosest)
                {
                    Merges = 1;
                    while (Merges > 0)
                    {
                        Merges = FindNextClosest(Paths);
                    }

                    int NewClosedCount = (from i in Paths where i.Closed == true select i).Count();

                    Console.WriteLine("remaining open: {0}", NewClosedCount);

                    /*
                     * var OpenPaths = (from i in Paths where i.Closed == false select i).ToArray();
                     * //  foreach (var p in OpenPaths)
                     * //  {
                     * //     Paths.Remove(p);
                     * //  }
                     *
                     * while (OpenPaths.Count() > 1)
                     * {
                     *  var P = OpenPaths[0];
                     *  var V = P.Points.Last();
                     *  double ClosestDistance = 1000000;
                     *  int closestindex = 0;
                     *  bool forward = true;
                     *
                     *  double OwnDistance = (P.Points.First() - P.Points.Last()).Length();
                     *  ClosestDistance = OwnDistance;
                     *  for (int i = 1; i < OpenPaths.Count(); i++)
                     *  {
                     *      double dx1 = OpenPaths[i].Points.First().X - V.X;
                     *      double dy1 = OpenPaths[i].Points.First().Y - V.Y;
                     *
                     *      double dx2 = OpenPaths[i].Points.Last().X - V.X;
                     *      double dy2 = OpenPaths[i].Points.Last().Y - V.Y;
                     *
                     *      float disttofirst = (float)Math.Sqrt(dx1 * dx1 + dy1 * dy1);
                     *      float disttolast = (float)Math.Sqrt(dx2 * dx2 + dy2 * dy2);
                     *
                     *      if (disttofirst < ClosestDistance)
                     *      {
                     *          forward = true;
                     *          closestindex = i;
                     *          ClosestDistance = disttofirst;
                     *      }
                     *
                     *      if (disttolast < ClosestDistance)
                     *      {
                     *          forward = false;
                     *          closestindex = i;
                     *          ClosestDistance = disttolast;
                     *      }
                     *
                     *  }
                     *  if (OwnDistance == ClosestDistance)
                     *  {
                     *      P.Closed = true;
                     *      //      Paths.Add(P);
                     *  }
                     *  else
                     *  {
                     *      if (forward)
                     *      {
                     *          var PJ = OpenPaths[closestindex];
                     *          P.Points.AddRange(PJ.Points);
                     *          Paths.Remove(PJ);
                     *      }
                     *      else
                     *      {
                     *          var PJ = OpenPaths[closestindex];
                     *          PJ.Points.Reverse();
                     *          P.Points.AddRange(PJ.Points);
                     *          Paths.Remove(PJ);
                     *      }
                     *      if (P.Points.First() == P.Points.Last())
                     *      {
                     *          P.Closed = true;
                     *      }
                     *  }
                     *
                     *
                     *  OpenPaths = (from i in Paths where i.Closed == false select i).ToArray();
                     *
                     * }*/
                }
            }
            List <PathDefWithClosed> Results = new List <PathDefWithClosed>();

            foreach (var p in Paths)
            {
                Results.Add(Sanitize(p));
            }
            return(Results);
        }
예제 #3
0
        public static List <List <PointD> > LineSegmentsToPolygons(List <List <PointD> > input, bool joinclosest = true)
        {
            List <PathDefWithClosed> Paths         = new List <PathDefWithClosed>();
            List <List <PointD> >    FirstSweep    = new List <List <PointD> >();
            List <List <PointD> >    LeftoverLines = new List <List <PointD> >();

            if (input.Count == 0)
            {
                return(LeftoverLines);
            }
            try
            {
                foreach (var p in input)
                {
                    if (p.Count > 0)
                    {
                        FirstSweep.Add(Sanitize(p));
                    }
                }
                LeftoverLines.Add(FirstSweep[0]);
                for (int i = 1; i < FirstSweep.Count; i++)
                {
                    var LastLeft  = LeftoverLines.Last();
                    var LastLeftP = LastLeft.Last();

                    if (FirstSweep[i].First() == LastLeftP)
                    {
                        LastLeft.AddRange(FirstSweep[i].Skip(1));
                    }
                    else
                    {
                        if (FirstSweep[i].Last() == LastLeftP)
                        {
                            FirstSweep[i].Reverse();

                            LastLeft.AddRange(FirstSweep[i].Skip(1));
                        }
                        else
                        {
                            LeftoverLines.Add(FirstSweep[i]);
                        }
                    }
                }
            }
            catch (Exception E)
            {
                Console.WriteLine(E.Message);
            }
            while (LeftoverLines.Count > 0)
            {
                bool added = false;

                var a = LeftoverLines.Last();
                LeftoverLines.Remove(a);
                #region oldcode
                //foreach (var P in Paths)
                //{
                //    if (added == false && P.Closed == false)
                //    {
                //        if (P.Points[0] == a.First())
                //        {
                //            if (P.Points.Last() == a.Last())
                //            {
                //                P.Closed = true;
                //            }
                //            else
                //            {
                //                P.Points.Insert(0, a.First());
                //            }
                //            added = true;
                //        }
                //        else
                //            if (P.Points[0] == a.Last())
                //            {
                //                P.Points.Insert(0, a.First());
                //                added = true;
                //            }
                //            else
                //                if (P.Points.Last() == a.First())
                //                {
                //                    P.Points.Add(a.Last());
                //                    added = true;
                //                }
                //                else
                //                    if (P.Points.Last() == a.Last())
                //                    {
                //                        P.Points.Add(a.First());
                //                        added = true;
                //                    }
                //                    else
                //                    {
                //                    }
                //    }
                //}
                #endregion
                if (added == false)
                {
                    PathDefWithClosed P = new PathDefWithClosed();
                    foreach (var v in a)
                    {
                        P.Points.Add(v);
                    }
                    //P.Points.Add(a.Last());
                    if (a.First() == a.Last())
                    {
                        int matching = 0;
                        for (int i = 0; i < a.Count / 2; i++)
                        {
                            if (a[i] == a[a.Count - 1 - i])
                            {
                                matching++;
                            }
                        }
                        if (matching > 1)
                        {
                            P.Points.Clear();
                            for (int i = 0; i < (a.Count + 1) / 2; i++)
                            {
                                P.Points.Add(a[i]);
                            }
                        }
                        else
                        {
                            a.Remove(a.Last());
//                            Console.WriteLine("closed path with {0} points during stage 2: {1} reversematched", a.Count(), matching);
                            P.Closed = true;
                        }
                    }
                    Paths.Add(P);
                }
            }

            int Merges   = 1;
            int startat  = 0;
            int lasthigh = 0;
            while (Merges > 0)
            {
                startat = lasthigh;
                Merges  = FindNextMerge(Paths, out lasthigh, startat);
            }

            int ClosedCount = (from i in Paths where i.Closed == true select i).Count();
            if (ClosedCount < Paths.Count)
            {
                //Console.WriteLine("{0}/{1} paths open - finding closest connections", Paths.Count - ClosedCount, Paths.Count);
                if (joinclosest)
                {
                    Merges = 1;
                    while (Merges > 0)
                    {
                        Merges = FindNextClosest(Paths);
                    }

                    /*
                     * var OpenPaths = (from i in Paths where i.Closed == false select i).ToArray();
                     * //  foreach (var p in OpenPaths)
                     * //  {
                     * //     Paths.Remove(p);
                     * //  }
                     *
                     * while (OpenPaths.Count() > 1)
                     * {
                     *  var P = OpenPaths[0];
                     *  var V = P.Points.Last();
                     *  double ClosestDistance = 1000000;
                     *  int closestindex = 0;
                     *  bool forward = true;
                     *
                     *  double OwnDistance = (P.Points.First() - P.Points.Last()).Length();
                     *  ClosestDistance = OwnDistance;
                     *  for (int i = 1; i < OpenPaths.Count(); i++)
                     *  {
                     *      double dx1 = OpenPaths[i].Points.First().X - V.X;
                     *      double dy1 = OpenPaths[i].Points.First().Y - V.Y;
                     *
                     *      double dx2 = OpenPaths[i].Points.Last().X - V.X;
                     *      double dy2 = OpenPaths[i].Points.Last().Y - V.Y;
                     *
                     *      float disttofirst = (float)Math.Sqrt(dx1 * dx1 + dy1 * dy1);
                     *      float disttolast = (float)Math.Sqrt(dx2 * dx2 + dy2 * dy2);
                     *
                     *      if (disttofirst < ClosestDistance)
                     *      {
                     *          forward = true;
                     *          closestindex = i;
                     *          ClosestDistance = disttofirst;
                     *      }
                     *
                     *      if (disttolast < ClosestDistance)
                     *      {
                     *          forward = false;
                     *          closestindex = i;
                     *          ClosestDistance = disttolast;
                     *      }
                     *
                     *  }
                     *  if (OwnDistance == ClosestDistance)
                     *  {
                     *      P.Closed = true;
                     *      //      Paths.Add(P);
                     *  }
                     *  else
                     *  {
                     *      if (forward)
                     *      {
                     *          var PJ = OpenPaths[closestindex];
                     *          P.Points.AddRange(PJ.Points);
                     *          Paths.Remove(PJ);
                     *      }
                     *      else
                     *      {
                     *          var PJ = OpenPaths[closestindex];
                     *          PJ.Points.Reverse();
                     *          P.Points.AddRange(PJ.Points);
                     *          Paths.Remove(PJ);
                     *      }
                     *      if (P.Points.First() == P.Points.Last())
                     *      {
                     *          P.Closed = true;
                     *      }
                     *  }
                     *
                     *
                     *  OpenPaths = (from i in Paths where i.Closed == false select i).ToArray();
                     *
                     * }*/
                }
            }
            List <List <PointD> > Results = new List <List <PointD> >();
            foreach (var p in Paths)
            {
                Results.Add(Sanitize(p.Points));
            }
            return(Results);
        }