예제 #1
0
        private bool turn_left(Vector p1, Vector p2, Vector p3)
        {
            var v1 = GeomMath.Subtract(p2, p1);
            var v2 = GeomMath.Subtract(p3, p2);

            return((v1.X * v2.Y - v2.X * v1.Y) > 0);
        }
예제 #2
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);
        }
예제 #3
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);
        }
예제 #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);
        }