예제 #1
0
        private int FindAngles(int[] e, double[] a, Vector v, Vector n)
        {
            Vector[] u = new Vector[4];

            //for (int i = 0; i < 4; i++)
            //    u[i] = (m_chull[(e[i] + 1) % size] - m_chull[e[i]]).normalize();

            int size = hull.Count;

            for (int i = 0; i < 4; i++)
            {
                u[i] = GeomMath.Subtract(hull[(e[i] + 1) % size], hull[e[i]]).normalize();
            }

            int w = 0;

            //a[0] = fabs(v * u[0]);
            //a[1] = fabs(n * u[1]); if (a[1] > a[w]) { w = 1; } //larger dot product means smaller angle
            //a[2] = fabs(v * u[2]); if (a[2] > a[w]) { w = 2; }
            //a[3] = fabs(n * u[3]); if (a[3] > a[w]) { w = 3; }

            a[0] = Math.Abs(GeomMath.DotProduct(v, u[0]));
            a[1] = Math.Abs(GeomMath.DotProduct(n, u[1]));

            if (a[1] > a[w])
            {
                w = 1;
            }

            a[2] = Math.Abs(GeomMath.DotProduct(v, u[2]));

            if (a[2] > a[w])
            {
                w = 2;
            }

            a[3] = Math.Abs(GeomMath.DotProduct(n, u[3]));

            if (a[3] > a[w])
            {
                w = 3;
            }

            return(w);
        }
예제 #2
0
        private BoundingBox CreateBoundingBox(int[] e, Vector v, Vector n)
        {
            //box.corners[0] = m_chull[e[0]] + v * ((m_chull[e[1]] - m_chull[e[0]]) * v);
            //box.corners[3] = m_chull[e[0]] + v * ((m_chull[e[3]] - m_chull[e[0]]) * v);
            //box.corners[1] = m_chull[e[2]] + v * ((m_chull[e[1]] - m_chull[e[2]]) * v);
            //box.corners[2] = m_chull[e[2]] + v * ((m_chull[e[3]] - m_chull[e[2]]) * v);

            //box.width = fabs((m_chull[e[3]] - m_chull[e[1]]) * v);
            //box.height = fabs((m_chull[e[2]] - m_chull[e[0]]) * n);

            var box = new BoundingBox();

            box.Corners[0] = GeomMath.Add(hull[e[0]], GeomMath.Multiply(v, GeomMath.DotProduct(GeomMath.Subtract(hull[e[1]], hull[e[0]]), v)));
            box.Corners[3] = GeomMath.Add(hull[e[0]], GeomMath.Multiply(v, GeomMath.DotProduct(GeomMath.Subtract(hull[e[3]], hull[e[0]]), v)));
            box.Corners[1] = GeomMath.Add(hull[e[2]], GeomMath.Multiply(v, GeomMath.DotProduct(GeomMath.Subtract(hull[e[1]], hull[e[2]]), v)));
            box.Corners[2] = GeomMath.Add(hull[e[2]], GeomMath.Multiply(v, GeomMath.DotProduct(GeomMath.Subtract(hull[e[3]], hull[e[2]]), v)));

            box.Width  = Math.Abs(GeomMath.DotProduct(GeomMath.Subtract(hull[e[3]], hull[e[1]]), v));
            box.Height = Math.Abs(GeomMath.DotProduct(GeomMath.Subtract(hull[e[2]], hull[e[0]]), n));

            return(box);
        }
예제 #3
0
        public void Compute()
        {
            SortPolygons();

            List <Vector> P = SortedPoly1;
            List <Vector> Q = SortedPoly2;

            int    n = SortedPoly1.Count;
            int    m = SortedPoly2.Count;
            int    a, b;
            int    a1, b1;
            Vector A = new Vector(), B = new Vector();
            int    cross;
            int    bHA, aHB;
            Vector origin = new Vector {
                X = 0, Y = 0
            };
            Vector p = new Vector(), q = new Vector();
            int    inFlag;
            int    aa, ba;
            bool   firstPoint;
            Vector p0 = new Vector();
            int    code;

            a          = 0; b = 0; aa = 0; ba = 0;
            inFlag     = INFLAG_UNKNOWN;
            firstPoint = true;

            activeStatusLayer = History.CreateAndAddNewLayer("Setup");
            activeStatusLayer.AddCommand(new AddTextStatusCommand {
                AssociatedAlgorithm = this,
                Comments            = "The 'in' flag starts as unknown, initial vectors start at index 0"
            });

            do
            {
                a1 = (a + n - 1) % n;
                b1 = (b + m - 1) % m;

                activeStatusLayer = History.CreateAndAddNewLayer("Main loop, a=" + a + ", b=" + b + ", a1=" + a1 + ", b1=" + b1);

                // SubVec(P[a], P[a1], A);
                A.X = P[a].X - P[a1].X;
                A.Y = P[a].Y - P[a1].Y;
                // SubVec(Q[b], Q[b1], B);
                B.X = Q[b].X - Q[b1].X;
                B.Y = Q[b].Y - Q[b1].Y;

                activeStatusLayer.AddCommand(new ClearTextStatusCommand {
                    AssociatedAlgorithm = this
                });
                AddNonIndexedLineCommand(activeStatusLayer, new Vector {
                    X = P[a1].X, Y = P[a1].Y
                }, new Vector {
                    X = P[a].X, Y = P[a].Y
                });
                AddNonIndexedLineCommand(activeStatusLayer, new Vector {
                    X = Q[b1].X, Y = Q[b1].Y
                }, new Vector {
                    X = Q[b].X, Y = Q[b].Y
                });

                cross = AreaSign(origin, A, B);
                aHB   = AreaSign(Q[b1], Q[b], P[a]);
                bHA   = AreaSign(P[a1], P[a], Q[b]);

                activeStatusLayer.AddCommand(new AddTextStatusCommand
                {
                    AssociatedAlgorithm = this,
                    Comments            = "cross=" + cross
                });
                activeStatusLayer.AddCommand(new AddTextStatusCommand
                {
                    AssociatedAlgorithm = this,
                    Comments            = "aHB=" + aHB
                });
                activeStatusLayer.AddCommand(new AddTextStatusCommand
                {
                    AssociatedAlgorithm = this,
                    Comments            = "bHA=" + bHA
                });

                code = SegSegInt(P[a1], P[a], Q[b1], Q[b], p, q);

                activeStatusLayer.AddCommand(new AddTextStatusCommand
                {
                    AssociatedAlgorithm = this,
                    Comments            = "Segment intersection status: " + TranslateCode(code)
                });

                if (code == STATUS_1 || code == STATUS_V)
                {
                    if (inFlag == STATUS_UNKNOWN && firstPoint)
                    {
                        aa         = 0;
                        ba         = 0;
                        firstPoint = false;
                        p0.X       = p.X;
                        p0.Y       = p.Y;
                        // moveto p0
                        MoveTo(p0);
                    }

                    LineTo(p);
                    inFlag = InOut(p, inFlag, aHB, bHA);

                    activeStatusLayer.AddCommand(new AddTextStatusCommand
                    {
                        AssociatedAlgorithm = this,
                        Comments            = "Newly computed 'in' flag: " + TranslateInOut(inFlag)
                    });
                }

                if (code == STATUS_E && GeomMath.DotProduct(A, B) < 0)
                {
                    activeStatusLayer.AddCommand(new AddTextStatusCommand
                    {
                        AssociatedAlgorithm = this,
                        Comments            = "Shared segement and ..."
                    });
                    // print shared segment
                    // return
                }

                if (cross == 0 && aHB < 0 && bHA < 0)
                {
                    // disjoint
                    // return
                    activeStatusLayer.AddCommand(new AddTextStatusCommand
                    {
                        AssociatedAlgorithm = this,
                        Comments            = "Polygons are disjoint"
                    });
                }
                else if (cross == 0 && aHB == 0 && bHA == 0)
                {
                    // advance but do not output point
                    // page 262
                    if (inFlag == INFLAG_PIN)
                    {
                        // b = Advance(b, &ba, m, inflag == Qin, Q[b]);
                        // if inFlag == Qin // always false here
                        //    lineto Q[b]
                        ba++;
                        b = (b + 1) % m;
                        activeStatusLayer.AddCommand(new AddTextStatusCommand
                        {
                            AssociatedAlgorithm = this,
                            Comments            = "Advancing b vector but not including in output as not part of interection"
                        });
                    }
                    else
                    {
                        // a = Advance(a, &aa, n, inflag == Pin, P[a]);
                        // if inFlag == Pin // always false here
                        //    lineto P[a]
                        aa++;
                        a = (a + 1) % n;
                        activeStatusLayer.AddCommand(new AddTextStatusCommand
                        {
                            AssociatedAlgorithm = this,
                            Comments            = "Advancing a vector but not including in output as not part of interection"
                        });
                    }
                }
                else if (cross >= 0)
                {
                    if (bHA > 0)
                    {
                        // if inflag == PIN
                        //    lineto P[a]
                        if (inFlag == INFLAG_PIN)
                        {
                            LineTo(P[a]);
                        }
                        aa++;
                        a = (a + 1) % n;
                        activeStatusLayer.AddCommand(new AddTextStatusCommand
                        {
                            AssociatedAlgorithm = this,
                            Comments            = "Advancing a vector and including in output as part of interection"
                        });
                    }
                    else
                    {
                        // if inflag == QIN
                        //    lineto Q[b]
                        if (inFlag == INFLAG_QIN)
                        {
                            LineTo(Q[b]);
                        }
                        ba++;
                        b = (b + 1) % m;
                        activeStatusLayer.AddCommand(new AddTextStatusCommand
                        {
                            AssociatedAlgorithm = this,
                            Comments            = "Advancing b vector and including in output as part of interection"
                        });
                    }
                }
                else
                {
                    // cross < 0
                    if (aHB > 0)
                    {
                        // if inflag == QIN
                        //    lineto Q[b]
                        if (inFlag == INFLAG_QIN)
                        {
                            LineTo(Q[b]);
                        }
                        ba++;
                        b = (b + 1) % m;
                        activeStatusLayer.AddCommand(new AddTextStatusCommand
                        {
                            AssociatedAlgorithm = this,
                            Comments            = "Advancing b vector and including in output as part of interection"
                        });
                    }
                    else
                    {
                        // if inflag == PIN
                        //     lineto P[a]
                        if (inFlag == INFLAG_PIN)
                        {
                            LineTo(P[a]);
                        }
                        aa++;
                        a = (a + 1) % n;
                        activeStatusLayer.AddCommand(new AddTextStatusCommand
                        {
                            AssociatedAlgorithm = this,
                            Comments            = "Advancing a vector and including in output as part of interection"
                        });
                    }
                }
            } while (((aa < n) || (ba < m)) && (aa < 2 * n) && (ba < 2 * m));

            if (aa >= 2 * n)
            {
                activeStatusLayer.AddCommand(new AddTextStatusCommand
                {
                    AssociatedAlgorithm = this,
                    Comments            = "Termination condition met: aa >= 2*n"
                });
            }
            else if (aa >= n)
            {
                activeStatusLayer.AddCommand(new AddTextStatusCommand
                {
                    AssociatedAlgorithm = this,
                    Comments            = "Termination condition met: aa >= n"
                });
            }

            if (ba >= 2 * m)
            {
                activeStatusLayer.AddCommand(new AddTextStatusCommand
                {
                    AssociatedAlgorithm = this,
                    Comments            = "Termination condition met: ba >= 2*m"
                });
            }
            else if (ba >= m)
            {
                activeStatusLayer.AddCommand(new AddTextStatusCommand
                {
                    AssociatedAlgorithm = this,
                    Comments            = "Termination condition met: ba >= m"
                });
            }

            if (!firstPoint)
            {
                // close intesection, line to p0
                LineTo(p0);
            }

            if (inFlag == INFLAG_UNKNOWN)
            {
                // boundaries do not cross
                activeStatusLayer.AddCommand(new AddTextStatusCommand
                {
                    AssociatedAlgorithm = this,
                    Comments            = "Boundaries of polygons do not cross, no intersection"
                });
            }
        }
예제 #4
0
        public BoundingBox FindSmallestBoundingBox()
        {
            //            mathtool::Vector2d v, n;
            //            int e[4]; //vertex indices of extreme points
            //            float a[4]; //angles
            //            int w; //index (0~3), so that e[w] has the smallest value a[w]
            //            int hullsize = m_chull.size();
            Vector v, n = new Vector();

            int[]    e = new int[4];
            double[] a = new double[4];
            int      w;

            //int hullsize = hull.Count;

            //            //init extreme points
            //            e[0] = 0;
            //            v = (m_chull[1] - m_chull[0]).normalize();
            //            n.set(-v[1], v[0]);
            //            const mathtool::Vector2d v0 = v;

            e[0] = 0;
            v    = GeomMath.Subtract(hull[1], hull[0]).normalize();
            n.X  = -v.Y;
            n.Y  = v.X;

            //Vector v0 = v;

            //            float max_v = -FLT_MAX, min_v = FLT_MAX, max_n = -FLT_MAX;
            //            for (int i = 2; i < hullsize; i++)
            //            {
            //                auto & pt = m_chull[i];
            //                double dv = (pt - m_chull[0]) * v;
            //                double dn = (pt - m_chull[0]) * n;
            //                if (dv > max_v) { max_v = dv; e[1] = i; }
            //                if (dv < min_v) { min_v = dv; e[3] = i; }
            //                if (dn > max_n) { max_n = dn; e[2] = i; }
            //            }

            double max_v = Double.MinValue;
            double min_v = Double.MaxValue;
            double max_n = Double.MinValue;

            for (int i = 2; i < hull.Count; i++)
            {
                Vector pt = hull[i];

                double dv = GeomMath.DotProduct(GeomMath.Subtract(pt, hull[0]), v);
                double dn = GeomMath.DotProduct(GeomMath.Subtract(pt, hull[0]), n);

                if (dv > max_v)
                {
                    max_v = dv;
                    e[1]  = i;
                }

                if (dv < min_v)
                {
                    min_v = dv;
                    e[3]  = i;
                }

                if (dn > max_n)
                {
                    max_n = dn;
                    e[2]  = i;
                }
            }

            //            w = findAngles(e, a, v, n);

            w = FindAngles(e, a, v, n);

            //            //update extreme points
            //            char svg_filename[256];

            //            for (int i = 0; i < m_chull.size(); i++)
            //            {

            //#if DEBUG
            //                cout << "box=" << box << endl;
            //                sprintf(svg_filename, "%s%03d.svg", "DEBUG_", i);
            //                saveSVG(svg_filename, m_chull_ply, box);
            //                //saveSVG(svg_filename,m_ply.front(),box);
            //#endif

            //            }

            double      smallestArea = Double.MaxValue;
            BoundingBox smallestBox  = null;

            for (int i = 0; i < hull.Count; i++)
            {
                //                //create a box from v,n,e[4]
                //                obb box = createOBB(e, v, n);
                var box = CreateBoundingBox(e, v, n);

                double area = box.Width * box.Height;

                if (smallestBox == null)
                {
                    smallestBox  = box;
                    smallestArea = area;
                }
                else if (area < smallestArea)
                {
                    smallestBox  = box;
                    smallestArea = area;
                }

                Console.WriteLine("Bounding Box #" + i + ": " + area);

                //                //check if this box solve the problem
                //                if (problem.solved(box)) break;

                //                //update
                //                int ne = (e[w] + 1) % hullsize;
                //                mathtool::Vector2d nev = (m_chull[ne] - m_chull[e[w]]).normalize();
                //                if (w == 0 || w == 2)
                //                {
                //                    v = nev;
                //                    n.set(-v[1], v[0]);
                //                }
                //                else
                //                {
                //                    n = nev;
                //                    v.set(-n[1], n[0]);
                //                }
                //                e[w] = ne;

                //                w = findAngles(e, a, v, n);
                int    ne  = (e[w] + 1) % hull.Count;
                Vector nev = GeomMath.Subtract(hull[ne], hull[e[w]]).normalize();

                if (w == 0 || w == 2)
                {
                    v   = nev;
                    n.X = -v.Y;
                    n.Y = v.X;
                }
                else
                {
                    n   = nev;
                    v.X = -n.Y;
                    v.Y = n.X;
                }

                e[w] = ne;
                w    = FindAngles(e, a, v, n);
            }

            return(smallestBox);
        }