Esempio n. 1
0
        public static IntersectionResolution GetIntersectionInfo(WeaklySimplePolygon lhs, WeaklySimplePolygon rhs)
        {
            IntersectionResolution res = new IntersectionResolution {
                intersections = new List <IntersectionPair>(),
                lhs           = new Dictionary <int, List <int> >(),
                rhs           = new Dictionary <int, List <int> >()
            };

            //-1 just refers to verts and not an index into holes
            for (int i = -1; i < lhs.holes.Count; i++)
            {
                LineLoop lhsLoop = (i == -1) ? lhs.verts : lhs.holes[i];
                for (int j = -1; j < rhs.holes.Count; j++)
                {
                    LineLoop rhsLoop = (j == -1) ? rhs.verts : rhs.holes[j];
                    List <LineLoop.LoopLoopIntersection> theseIntersections = LineLoop.AllIntersections(lhsLoop, rhsLoop);

                    foreach (LineLoop.LoopLoopIntersection info in theseIntersections)
                    {
                        gvec2 lhsDir = lhsLoop[info.lhsIndex + 1] - lhsLoop[info.lhsIndex];
                        gvec2 rhsDir = rhsLoop[info.rhsIndex + 1] - rhsLoop[info.rhsIndex];

                        TraversalMode lhsMode = gvec2.Dot(lhsDir, rhsDir.RotatedCCW90()) > 0 ? TraversalMode.entering : TraversalMode.exiting;
                        TraversalMode rhsMode = gvec2.Dot(rhsDir, lhsDir.RotatedCCW90()) > 0 ? TraversalMode.entering : TraversalMode.exiting;

                        res.intersections.Add(new IntersectionPair {
                            vert = info.position,
                            lhs  = new IntersectionInfo {
                                index   = i,
                                segment = info.lhsIndex,
                                param   = info.lhsParam,
                                mode    = lhsMode
                            },
                            rhs = new IntersectionInfo {
                                index   = j,
                                segment = info.rhsIndex,
                                param   = info.rhsParam,
                                mode    = rhsMode
                            }
                        });

                        if (!res.lhs.ContainsKey(i))
                        {
                            res.lhs[i] = new List <int>();
                        }
                        res.lhs[i].Add(res.intersections.Count - 1);
                        if (!res.rhs.ContainsKey(j))
                        {
                            res.rhs[j] = new List <int>();
                        }
                        res.rhs[j].Add(res.intersections.Count - 1);
                    }
                }
            }

            return(res);
        }
Esempio n. 2
0
        public WeaklySimplePolygon Clone()
        {
            WeaklySimplePolygon res = new WeaklySimplePolygon {
                verts = verts.Clone(),
                holes = new List <LineLoop>()
            };

            foreach (LineLoop hole in holes)
            {
                res.holes.Add(hole.Clone());
            }
            return(res);
        }
Esempio n. 3
0
 public void AccumulateWeaklySimplyPolygons(List <WeaklySimplePolygon> accumulator)
 {
     if (loop.Winding == WindingDir.ccw)
     {
         WeaklySimplePolygon p = new WeaklySimplePolygon();
         p.verts = loop;
         foreach (PolygonNode n in children)
         {
             p.holes.Add(n.loop);
         }
         accumulator.Add(p);
     }
     foreach (PolygonNode n in children)
     {
         n.AccumulateWeaklySimplyPolygons(accumulator);
     }
 }
Esempio n. 4
0
        public static WeaklySimplePolygon Union(WeaklySimplePolygon lhs, WeaklySimplePolygon rhs)
        {
            WeaklySimplePolygon res = new WeaklySimplePolygon();

            IntersectionResolution ir = GetIntersectionInfo(lhs, rhs);

            //preprocessing
            for (int i = -1; i < lhs.holes.Count; i++)
            {
                if (i == -1 && (!ir.lhs.ContainsKey(-1)) && !lhs.verts[0].IsInside(rhs))
                {
                }
                //if(ir.lhs.ContainsKey()
            }


            List <IntersectionPair> currentLoop = new List <IntersectionPair>();

            //this loop finds the next IntersectionPair in the loop
            //and when a loop is complete, outputs it into res
            while (ir.intersections.Count != 0)
            {
                //start off a random pair if we need to
                if (currentLoop.Count == 0)
                {
                    currentLoop.Add(ir.intersections[0]);
                }

                //find the next intersection and store it in nearestIntersection
                IntersectionPair nearestIntersection = null;
                IntersectionPair lastIntersection    = currentLoop.Last();
                TraversalMode    mode = (lastIntersection.lhs.mode == TraversalMode.exiting) ? TraversalMode.lhs : TraversalMode.rhs;
                //Dictionary<int, int> nextQueue =

                foreach (IntersectionPair info in ir.intersections)
                {
                    if (info.lhs.index == lastIntersection.lhs.index && info.rhs.index == lastIntersection.rhs.index && info != lastIntersection)
                    {
                        if (mode == TraversalMode.lhs)
                        {
                            //traversing lhs
                            if (nearestIntersection == null)
                            {
                                nearestIntersection = info;
                            }
                            else
                            {
                                if (nearestIntersection.lhs.dist < lastIntersection.lhs.dist)
                                {
                                    if (info.lhs.dist > lastIntersection.lhs.dist || info.lhs.dist < nearestIntersection.lhs.dist)
                                    {
                                        nearestIntersection = info;
                                    }
                                }
                                else
                                {
                                    if (info.lhs.dist < nearestIntersection.lhs.dist && info.lhs.dist > lastIntersection.lhs.dist)
                                    {
                                        nearestIntersection = info;
                                    }
                                }
                            }
                        }
                        else
                        {
                            //traversing rhs
                            if (nearestIntersection == null)
                            {
                                nearestIntersection = info;
                            }
                            else
                            {
                                if (nearestIntersection.rhs.dist < lastIntersection.rhs.dist)
                                {
                                    if (info.rhs.dist > lastIntersection.rhs.dist || info.rhs.dist < nearestIntersection.rhs.dist)
                                    {
                                        nearestIntersection = info;
                                    }
                                }
                                else
                                {
                                    if (info.rhs.dist < nearestIntersection.rhs.dist && info.rhs.dist > lastIntersection.rhs.dist)
                                    {
                                        nearestIntersection = info;
                                    }
                                }
                            }
                        }
                    }
                }

                //do what we must with this intersection, we might be done with the loop
                if (nearestIntersection == currentLoop.First())
                {
                    //loop is done, create the loop with actual segments and such
                    LineLoop loop = new LineLoop();

                    //segment mode
                    TraversalMode segMode = (currentLoop.First().lhs.mode == TraversalMode.exiting) ? TraversalMode.lhs : TraversalMode.rhs;
                    for (int i = 0; i < currentLoop.Count; i++)
                    {
                        IntersectionPair info     = currentLoop[i];
                        IntersectionPair nextInfo = currentLoop[(i + 1) % currentLoop.Count];

                        loop.Add(info.vert);

                        //select the correct polygon and loop
                        WeaklySimplePolygon opPoly    = (segMode == TraversalMode.lhs) ? lhs : rhs;
                        int      loopIndex            = (segMode == TraversalMode.lhs) ? info.lhs.index : info.rhs.index;
                        LineLoop opLoop               = (loopIndex == -1) ? opPoly.verts : opPoly.holes[loopIndex];
                        int      startSegment         = ((segMode == TraversalMode.lhs) ? (info.lhs.segment + 1) : info.rhs.segment + 1) % opLoop.Count;
                        int      endSegment           = (segMode == TraversalMode.lhs) ? nextInfo.lhs.segment : nextInfo.rhs.segment;
                        int      endSegmentPlusOneMod = (endSegment + 1) % opLoop.Count;

                        bool first = (segMode == TraversalMode.lhs) ? (info.lhs.dist > nextInfo.lhs.dist) : (info.rhs.dist > nextInfo.rhs.dist);
                        for (int currentSegment = startSegment;
                             (currentSegment != endSegmentPlusOneMod) || first;
                             currentSegment = (currentSegment + 1) % opLoop.Count)
                        {
                            loop.Add(opLoop[currentSegment]);
                            if (first)
                            {
                                first = false;
                            }
                        }

                        if (segMode == TraversalMode.lhs)
                        {
                            segMode = TraversalMode.rhs;
                        }
                        else
                        {
                            segMode = TraversalMode.lhs;
                        }
                    }

                    res.holes.Add(loop);

                    foreach (IntersectionPair info in currentLoop)
                    {
                        ir.intersections.Remove(info);
                    }
                    currentLoop.Clear();
                }
                else
                {
                    currentLoop.Add(nearestIntersection);
                }
            }

            return(res);
        }