Beispiel #1
0
 public Intersecter(bool selfIntersection, BuildLog buildLog = null)
 {
     this.selfIntersection = selfIntersection;
     this.buildLog         = buildLog;
 }
Beispiel #2
0
 public static SegmentList xor(SegmentList segments, BuildLog buildLog)
 {
     return(select(segments, xor_select_table, buildLog));
 }
Beispiel #3
0
 public static SegmentList differenceRev(SegmentList segments, BuildLog buildLog)
 {
     return(select(segments, differenceRev_select_table, buildLog));
 }
Beispiel #4
0
 public static SegmentList intersect(SegmentList segments, BuildLog buildLog)
 {
     return(select(segments, intersect_select_table, buildLog));
 }
Beispiel #5
0
 public static SegmentList union(SegmentList segments, BuildLog buildLog)
 {
     return(select(segments, union_select_table, buildLog));
 }
Beispiel #6
0
        public List <PointList> chain(SegmentList segments, BuildLog buildLog = null)
        {
            this.buildLog = buildLog;
            this.chains   = new List <PointList>();
            this.regions  = new List <PointList>();

            foreach (var seg in segments)
            {
                var pt1 = seg.start;
                var pt2 = seg.end;

                if (Epsilon.pointsSame(pt1, pt2))
                {
                    Console.WriteLine("PolyBool: Warning: Zero-length segment detected; your epsilon is probably too small or too large");
                    continue;
                }

                if (buildLog != null)
                {
                    buildLog.chainStart(seg);
                }

                first_match = new Match()
                {
                    index        = 0,
                    matches_head = false,
                    matches_pt1  = false
                };

                second_match = new Match()
                {
                    index        = 0,
                    matches_head = false,
                    matches_pt1  = false
                };

                next_match = first_match;

                for (var i = 0; i < chains.Count; i++)
                {
                    var chain = chains[i];
                    var head  = chain[0];
                    var head2 = chain[1];
                    var tail  = chain[chain.Count - 1];
                    var tail2 = chain[chain.Count - 2];

                    if (Epsilon.pointsSame(head, pt1))
                    {
                        if (setMatch(i, true, true))
                        {
                            break;
                        }
                    }
                    else if (Epsilon.pointsSame(head, pt2))
                    {
                        if (setMatch(i, true, false))
                        {
                            break;
                        }
                    }
                    else if (Epsilon.pointsSame(tail, pt1))
                    {
                        if (setMatch(i, false, true))
                        {
                            break;
                        }
                    }
                    else if (Epsilon.pointsSame(tail, pt2))
                    {
                        if (setMatch(i, false, false))
                        {
                            break;
                        }
                    }
                }

                if (next_match == first_match)
                {
                    // we didn't match anything, so create a new chain
                    chains.Add(new PointList()
                    {
                        pt1, pt2
                    });

                    if (buildLog != null)
                    {
                        buildLog.chainNew(pt1, pt2);
                    }

                    continue;
                }

                if (next_match == second_match)
                {
                    // we matched a single chain

                    if (buildLog != null)
                    {
                        buildLog.chainMatch(first_match.index);
                    }

                    // add the other point to the apporpriate end, and check to see if we've closed the
                    // chain into a loop

                    var index     = first_match.index;
                    var pt        = first_match.matches_pt1 ? pt2 : pt1;          // if we matched pt1, then we add pt2, etc
                    var addToHead = first_match.matches_head;                     // if we matched at head, then add to the head

                    var chain = chains[index];
                    var grow  = addToHead ? chain[0] : chain[chain.Count - 1];
                    var grow2 = addToHead ? chain[1] : chain[chain.Count - 2];
                    var oppo  = addToHead ? chain[chain.Count - 1] : chain[0];
                    var oppo2 = addToHead ? chain[chain.Count - 2] : chain[1];

                    if (Epsilon.pointsCollinear(grow2, grow, pt))
                    {
                        // grow isn't needed because it's directly between grow2 and pt:
                        // grow2 ---grow---> pt
                        if (addToHead)
                        {
                            if (buildLog != null)
                            {
                                buildLog.chainRemoveHead(first_match.index, pt);
                            }

                            chain.RemoveAt(0);
                        }
                        else
                        {
                            if (buildLog != null)
                            {
                                buildLog.chainRemoveTail(first_match.index, pt);
                            }

                            chain.RemoveAt(chain.Count - 1);
                        }
                        grow = grow2;                         // old grow is gone... new grow is what grow2 was
                    }

                    if (Epsilon.pointsSame(oppo, pt))
                    {
                        // we're closing the loop, so remove chain from chains
                        chains.RemoveAt(index);

                        if (Epsilon.pointsCollinear(oppo2, oppo, grow))
                        {
                            // oppo isn't needed because it's directly between oppo2 and grow:
                            // oppo2 ---oppo--->grow
                            if (addToHead)
                            {
                                if (buildLog != null)
                                {
                                    buildLog.chainRemoveTail(first_match.index, grow);
                                }

                                chain.RemoveAt(chain.Count - 1);
                            }
                            else
                            {
                                if (buildLog != null)
                                {
                                    buildLog.chainRemoveHead(first_match.index, grow);
                                }

                                chain.RemoveAt(0);
                            }
                        }

                        if (buildLog != null)
                        {
                            buildLog.chainClose(first_match.index);
                        }

                        // we have a closed chain!
                        regions.Add(chain);
                        continue;
                    }

                    // not closing a loop, so just add it to the apporpriate side
                    if (addToHead)
                    {
                        if (buildLog != null)
                        {
                            buildLog.chainAddHead(first_match.index, pt);
                        }

                        chain.Insert(0, pt);
                    }
                    else
                    {
                        if (buildLog != null)
                        {
                            buildLog.chainAddTail(first_match.index, pt);
                        }

                        chain.Add(pt);
                    }

                    continue;
                }

                // otherwise, we matched two chains, so we need to combine those chains together

                var F = first_match.index;
                var S = second_match.index;

                if (buildLog != null)
                {
                    buildLog.chainConnect(F, S);
                }

                var reverseF = chains[F].Count < chains[S].Count;                     // reverse the shorter chain, if needed
                if (first_match.matches_head)
                {
                    if (second_match.matches_head)
                    {
                        if (reverseF)
                        {
                            // <<<< F <<<< --- >>>> S >>>>
                            reverseChain(F);
                            // >>>> F >>>> --- >>>> S >>>>
                            appendChain(F, S);
                        }
                        else
                        {
                            // <<<< F <<<< --- >>>> S >>>>
                            reverseChain(S);
                            // <<<< F <<<< --- <<<< S <<<<   logically same as:
                            // >>>> S >>>> --- >>>> F >>>>
                            appendChain(S, F);
                        }
                    }
                    else
                    {
                        // <<<< F <<<< --- <<<< S <<<<   logically same as:
                        // >>>> S >>>> --- >>>> F >>>>
                        appendChain(S, F);
                    }
                }
                else
                {
                    if (second_match.matches_head)
                    {
                        // >>>> F >>>> --- >>>> S >>>>
                        appendChain(F, S);
                    }
                    else
                    {
                        if (reverseF)
                        {
                            // >>>> F >>>> --- <<<< S <<<<
                            reverseChain(F);
                            // <<<< F <<<< --- <<<< S <<<<   logically same as:
                            // >>>> S >>>> --- >>>> F >>>>
                            appendChain(S, F);
                        }
                        else
                        {
                            // >>>> F >>>> --- <<<< S <<<<
                            reverseChain(S);
                            // >>>> F >>>> --- >>>> S >>>>
                            appendChain(F, S);
                        }
                    }
                }
            }

            return(regions);
        }