예제 #1
0
 public Path2D(List<PolyLine3d> pls3d)
 {
     try
     {
         points = new List<Point2D>();
         segments = new List<Segment2D>();
         polys = new List<Polyline2D>();
         minx = miny = Double.MaxValue;
         maxx = maxy = Double.MinValue;
         // create dummy points to help with sorting
         GetCreatePoint(0, 0);
         //GetCreatePoint(1000000, 1000000);
         foreach (PolyLine3d p3d in pls3d)
         {
             Point2D pt1 = GetCreatePoint(p3d.m_points[0].x, p3d.m_points[0].y);
             Point2D pt2 = GetCreatePoint(p3d.m_points[1].x, p3d.m_points[1].y);
             if (Object.ReferenceEquals(pt1, pt2)) // invalid segment
                 continue;
             Segment2D seg = new Segment2D(pt1, pt2, p3d.m_derived.m_normal.x, p3d.m_derived.m_normal.y);
             segments.Add(seg);
         }
         FindIntersections();
         RemoveRedundant();
         ConstructPolyLines();
     }
     catch (Exception ex)
     {
         DebugLogger.Instance().LogError(ex);
     }
 }
예제 #2
0
        public double a, b;         // for y = a * x + b

        public SegPoint(Segment2D seg, int segix, bool isleft)
        {
            isLeft = isleft;
            if (isleft)
            {
                pt = seg.p1.CompareTo(seg.p2) < 0 ? seg.p1 : seg.p2;
                if (seg.p1.x == seg.p2.x)
                {
                    a = 0;
                    b = pt.y;
                }
                else
                {
                    a = (seg.p2.y - seg.p1.y) / (seg.p2.x - seg.p1.x);
                    b = seg.p2.y - a * seg.p2.x;
                }
            }
            else
            {
                pt = seg.p1.CompareTo(seg.p2) < 0 ? seg.p2 : seg.p1;
            }
            this.seg   = seg;
            this.segix = segix;
        }
예제 #3
0
        public void Add(Segment2D seg)
        {
            // horizontal
            if (Math.Abs(seg.p1.x - seg.p2.x) > Path2D.Epsilon)
            {
                int from = (int)((seg.pmin.x - minx - thgap) / hgap);
                if (from < 0)
                    from = 0;
                int to = (int)((seg.pmax.x - minx + thgap) / hgap);
                for (int i = from; i <= to; i++)
                    hbins[i].Add(seg);
            }

            // vertical
            if (Math.Abs(seg.p1.y - seg.p2.y) > Path2D.Epsilon)
            {
                int from = (int)((seg.pmin.y - miny - tvgap) / vgap);
                if (from < 0)
                    from = 0;
                int  to = (int)((seg.pmax.y - miny + tvgap) / vgap);
                for (int i = from; i <= to; i++)
                    vbins[i].Add(seg);
            }
        }
예제 #4
0
        // find intersection between 2 segments. if they do intersect return new segments after
        // splitting originals on the intersection point.
        public List<Segment2D> Intersect(Segment2D seg, Path2D path)
        {
            // quickly eliminate non adjacent lines
            if ((seg.pmax.y <= pmin.y) || (seg.pmin.y >= pmax.y) || (seg.pmax.x <= pmin.x) || (seg.pmin.x >= pmax.x))
                return null;

            // special case 1: sigments have same endpoints, nothing to do
            if ((Object.ReferenceEquals(p1, seg.p1) && Object.ReferenceEquals(p2, seg.p2)) ||
                (Object.ReferenceEquals(p2, seg.p1) && Object.ReferenceEquals(p1, seg.p2)))
                return null;

            double x21 = p2.x - p1.x;
            double x43 = seg.p2.x - seg.p1.x;
            double y21 = p2.y - p1.y;
            double y43 = seg.p2.y - seg.p1.y;

            double c = x21 * y43 - y21 * x43;

            List<Segment2D> segments;
            // if lines are parrallel, nothing to do
            if (Math.Abs(c) <= Path2D.DEpsilon)
                return null;

            // lines are not parallel. if both lines share any edge, nothing to do
            if (Object.ReferenceEquals(p1, seg.p1) || Object.ReferenceEquals(p2, seg.p2) ||
                Object.ReferenceEquals(p2, seg.p1) || Object.ReferenceEquals(p1, seg.p2))
                return null;

            double x31 = seg.p1.x - p1.x;
            double y31 = seg.p1.y - p1.y;

            double u = (y43 * x31 - x43 * y31) / c;
            double v = (y21 * x31 - x21 * y31) / c;

            // if u or v are outside the 0-1 range, no intersection
            if ((u < -Path2D.Epsilon) || (u > 1 + Path2D.Epsilon) || (v < -Path2D.Epsilon) || (v > 1 + Path2D.Epsilon))
                return null;

            // get intersection point
            Point2D ip = path.GetCreatePoint(p1.x + u * x21, p1.y + u * y21);

            segments = new List<Segment2D>();
            // if ip is not on edge of lines, split them
            if (!Object.ReferenceEquals(p1, ip) && !Object.ReferenceEquals(p2, ip))
                segments.AddRange(SplitAt(ip));
            else
                segments.Add(this);
            if (!Object.ReferenceEquals(seg.p1, ip) && !Object.ReferenceEquals(seg.p2, ip))
                segments.AddRange(seg.SplitAt(ip));
            else
                segments.Add(seg);
            return segments;
        }
예제 #5
0
 // this function finds intersection of seg with y line
 // if no intersection or intersecton too close to x, do nothing
 // find position of intersection, if it is to the right of x, update rightCount with segment direction
 // otherwise update leftCount with segment direction
 public void UpdateYcrossing(double y, double x, Segment2D seg, ref int leftCount, ref int rightCount)
 {
     int dir = 0;
     if ((y >= seg.p1.y) && (y < seg.p2.y))
         dir = -1;
     else if ((y <= seg.p1.y) && (y > seg.p2.y))
         dir = 1;
     if (dir != 0)
     {
         double u = (y - seg.p1.y) / (seg.p2.y - seg.p1.y);
         double xpos = seg.p1.x + u * (seg.p2.x - seg.p1.x);
         if (Math.Abs(xpos - x) > Path2D.Epsilon)
         {
             if (xpos > x)
                 rightCount += dir;
             else
                 leftCount -= dir;
         }
     }
 }
예제 #6
0
 // same as UpdateYcrossing but in vertical direction
 public void UpdateXcrossing(double x, double y, Segment2D seg, ref int botCount, ref int topCount)
 {
     int dir = 0;
     if ((x >= seg.p1.x) && (x < seg.p2.x))
         dir = 1;
     else if ((x <= seg.p1.x) && (x > seg.p2.x))
         dir = -1;
     if (dir != 0)
     {
         double u = (x - seg.p1.x) / (seg.p2.x - seg.p1.x);
         double ypos = seg.p1.y + u * (seg.p2.y - seg.p1.y);
         if (Math.Abs(ypos - y) > Path2D.Epsilon)
         {
             if (ypos > y)
                 topCount += dir;
             else
                 botCount -= dir;
         }
     }
 }
예제 #7
0
        // segments represent an edge where the right side is inside the object and the left side is
        // outside. when objects intersect some segments fall totaly inside the object. (left and right
        // side is in the object). These segments are now redundant so we remove them.
        public void RemoveRedundant()
        {
            int i, j, n_nonhoriz;
            List <Segment2D> lineSegs;

            try
            {
                // collect all horizontal segments and push them to the end, they will be processed in the vertical sweep
                n_nonhoriz = segments.Count;
                for (i = 0; i < n_nonhoriz; i++)
                {
                    while ((i < n_nonhoriz) && (Math.Abs(segments[i].p1.y - segments[i].p2.y) <= Path2D.Epsilon))
                    {
                        Segment2D seg = segments[i];
                        segments.RemoveAt(i);
                        segments.Add(seg);
                        n_nonhoriz--;
                    }
                }
                SegmentBin sbin = new SegmentBin(minx, miny, maxx, maxy, 100);
                sbin.Add(segments);

                // horizontal sweep
                for (i = 0; i < n_nonhoriz; i++)
                {
                    Segment2D seg        = segments[i];
                    double    y          = seg.p1.y + 0.61263546 * (seg.p2.y - seg.p1.y); // arbitrary point between y1 and y2.
                    double    u          = (y - seg.p1.y) / (seg.p2.y - seg.p1.y);
                    double    xpos       = seg.p1.x + u * (seg.p2.x - seg.p1.x);
                    int       rightCount = 0;
                    int       leftCount  = 0;

                    /*for (j = 0; j < n_nonhoriz; j++)
                     * {
                     *  if (j == i)
                     *      continue;
                     *  UpdateYcrossing(y, xpos, segments[j], ref leftCount, ref rightCount);
                     * }*/
                    lineSegs = sbin.GetVbin(y);
                    foreach (Segment2D seg1 in lineSegs)
                    {
                        if (!Object.ReferenceEquals(seg, seg1))
                        {
                            UpdateYcrossing(y, xpos, seg1, ref leftCount, ref rightCount);
                        }
                    }
                    // mark valid only the segments that one side count is zero and the other non zero
                    if (((leftCount == 0) && (rightCount != 0)) || ((leftCount != 0) && (rightCount == 0)))
                    {
                        seg.isValid = true;
                    }
                }

                // vertical sweep
                for (i = n_nonhoriz; i < segments.Count; i++)
                {
                    Segment2D seg      = segments[i];
                    double    x        = seg.p1.x + 0.61263546f * (seg.p2.x - seg.p1.x); // arbitrary point between y1 and y2.
                    double    u        = (x - seg.p1.x) / (seg.p2.x - seg.p1.x);
                    double    ypos     = seg.p1.y + u * (seg.p2.y - seg.p1.y);
                    int       topCount = 0;
                    int       botCount = 0;

                    /*for (j = 0; j < segments.Count; j++)
                     * {
                     *  if ((j == i) || (Math.Abs(segments[j].p1.x - segments[j].p2.x) <= Path2D.Epsilon)) // skip vertical lines
                     *      continue;
                     *  UpdateXcrossing(x, ypos, segments[j], ref botCount, ref topCount);
                     * }*/
                    lineSegs = sbin.GetHbin(x);
                    foreach (Segment2D seg1 in lineSegs)
                    {
                        if (!Object.ReferenceEquals(seg, seg1))
                        {
                            UpdateXcrossing(x, ypos, seg1, ref botCount, ref topCount);
                        }
                    }

                    // mark valid only the segments that one side count is zero and the other non zero
                    if (((botCount == 0) && (topCount != 0)) || ((botCount != 0) && (topCount == 0)))
                    {
                        seg.isValid = true;
                    }
                }
            }
            catch (Exception ex)
            {
                DebugLogger.Instance().LogError(ex);
            }
        }
예제 #8
0
        // find intersection between 2 segments. if they do intersect return new segments after
        // splitting originals on the intersection point.
        public List <Segment2D> Intersect(Segment2D seg, Path2D path)
        {
            // quickly eliminate non adjacent lines
            if ((seg.pmax.y <= pmin.y) || (seg.pmin.y >= pmax.y) || (seg.pmax.x <= pmin.x) || (seg.pmin.x >= pmax.x))
            {
                return(null);
            }

            // special case 1: sigments have same endpoints, nothing to do
            if ((Object.ReferenceEquals(p1, seg.p1) && Object.ReferenceEquals(p2, seg.p2)) ||
                (Object.ReferenceEquals(p2, seg.p1) && Object.ReferenceEquals(p1, seg.p2)))
            {
                return(null);
            }

            double x21 = p2.x - p1.x;
            double x43 = seg.p2.x - seg.p1.x;
            double y21 = p2.y - p1.y;
            double y43 = seg.p2.y - seg.p1.y;

            double c = x21 * y43 - y21 * x43;

            List <Segment2D> segments;

            // if lines are parrallel, nothing to do
            if (Math.Abs(c) <= Path2D.DEpsilon)
            {
                return(null);
            }

            // lines are not parallel. if both lines share any edge, nothing to do
            if (Object.ReferenceEquals(p1, seg.p1) || Object.ReferenceEquals(p2, seg.p2) ||
                Object.ReferenceEquals(p2, seg.p1) || Object.ReferenceEquals(p1, seg.p2))
            {
                return(null);
            }

            double x31 = seg.p1.x - p1.x;
            double y31 = seg.p1.y - p1.y;

            double u = (y43 * x31 - x43 * y31) / c;
            double v = (y21 * x31 - x21 * y31) / c;

            // if u or v are outside the 0-1 range, no intersection
            if ((u < -Path2D.Epsilon) || (u > 1 + Path2D.Epsilon) || (v < -Path2D.Epsilon) || (v > 1 + Path2D.Epsilon))
            {
                return(null);
            }

            // get intersection point
            Point2D ip = path.GetCreatePoint(p1.x + u * x21, p1.y + u * y21);

            segments = new List <Segment2D>();
            // if ip is not on edge of lines, split them
            if (!Object.ReferenceEquals(p1, ip) && !Object.ReferenceEquals(p2, ip))
            {
                segments.AddRange(SplitAt(ip));
            }
            else
            {
                segments.Add(this);
            }
            if (!Object.ReferenceEquals(seg.p1, ip) && !Object.ReferenceEquals(seg.p2, ip))
            {
                segments.AddRange(seg.SplitAt(ip));
            }
            else
            {
                segments.Add(seg);
            }
            return(segments);
        }