예제 #1
0
        public BoundingBox(Point[] corners)
        {
            // compute the fourth point of the rotated rect, pt4 = pt3 - pt2 + p1
            this.corners = new Point[4];
            for (int i = 0; i < 3; i++)
            {
                this.corners[i] = corners[i];
            }
            this.corners[3] = PA.Add(PA.Subtract(corners[2], corners[1]), corners[0]);

            // reorder points
            this.corners = reOderPoints(this.corners);
            this.length  = PA.Norm(this.corners[0], this.corners[1]);
            this.width   = PA.Norm(this.corners[0], this.corners[3]);
            this.angle   = Math.Atan2(this.corners[1].Y - this.corners[0].Y,
                                      this.corners[1].X - this.corners[0].X) / Math.PI * 180;
            this.angle = this.angle > 90 ? this.angle - 180 : this.angle; // (-90, 90]
            // compute the center of rotated rect
            int xc = 0, yc = 0;

            for (int i = 0; i < 4; i++)
            {
                xc += this.corners[i].X;
                yc += this.corners[i].Y;
            }
            this.center = new Point(xc / 4, yc / 4);
        }
예제 #2
0
        public bool Contains(Point pt)
        {
            // roate the rectangle angle degree counter-clockwise
            Point[] ptsRotated = new Point[4];
            Point   transpt;
            int     x, y;
            double  sin   = Math.Sin(angle / 180 * Math.PI);
            double  cosin = Math.Cos(angle / 180 * Math.PI);

            for (int i = 0; i < 4; i++)
            {
                transpt       = PA.Subtract(corners[i], center);
                x             = Convert.ToInt32(transpt.X * cosin + transpt.Y * sin + center.X);
                y             = Convert.ToInt32(transpt.X * -sin + transpt.Y * cosin + center.Y);
                ptsRotated[i] = new Point(x, y);
            }
            List <int> xs = ptsRotated.OrderBy(p => p.X).Select(p => p.X).ToList();
            List <int> ys = ptsRotated.OrderBy(p => p.Y).Select(p => p.Y).ToList();
            //Size size = new Size(Math.Abs(ptsRotated[0].X - ptsRotated[2].X),
            //                     Math.Abs(ptsRotated[0].Y - ptsRotated[2].Y));
            Rectangle rect = new Rectangle(xs[0], ys[0], xs[3] - xs[0], ys[3] - ys[0]);

            // apply rotation to point p
            transpt = new Point(pt.X - center.X, pt.Y - center.Y);
            x       = Convert.ToInt32(transpt.X * cosin + transpt.Y * sin + center.X);
            y       = Convert.ToInt32(transpt.X * -sin + transpt.Y * cosin + center.Y);
            bool isContained = rect.Contains(new Point(x, y));

            return(isContained);
        }
예제 #3
0
        public void ShiftCornerTo(int ind, Point pt)
        {
            if (PA.Norm(pt, corners[ind]) < 1)
            {
                return;
            }
            // recompute the coordinates of two adjacent points of this shifted point
            Point prjpt1 = PA.Project2Vector(corners[(ind + 2) % 4], corners[(ind + 1) % 4], pt);
            Point prjpt2 = PA.Project2Vector(corners[(ind + 2) % 4], corners[(ind + 3) % 4], pt);

            // rectify projected pt2/pt1 make sure two vectors formed by these three points are well orthogonal
            prjpt2 = PA.Project2NormalVector(corners[(ind + 2) % 4], prjpt1, prjpt2);

            this.corners[(ind + 1) % 4] = prjpt1;
            this.corners[(ind + 3) % 4] = prjpt2;
            // update the shifted point itself
            this.corners[ind] = pt;
            // reorder
            this.corners = reOderPoints(this.corners);
            // update width, length
            this.length = PA.Norm(this.corners[0], this.corners[1]);
            this.width  = PA.Norm(this.corners[0], this.corners[3]);
            this.angle  = Math.Atan2(this.corners[1].Y - this.corners[0].Y,
                                     this.corners[1].X - this.corners[0].X) / Math.PI * 180;
            this.angle = this.angle > 90 ? this.angle - 180 : this.angle; // (-90, 90]
            // update the center of new rotated rect
            int xc = 0, yc = 0;

            for (int i = 0; i < 4; i++)
            {
                xc += this.corners[i].X;
                yc += this.corners[i].Y;
            }
            this.center = new Point(xc / 4, yc / 4);
        }
예제 #4
0
        public static Point Project2Vector(Point pt1, Point pt2, Point pt3)
        {
            // project a vector v1 formed by pt1-pt3 into another vector v2 formed by pt1-pt2
            Point  v1            = PA.Subtract(pt3, pt1);
            Point  v2            = PA.Subtract(pt2, pt1);
            float  scale         = (float)(PA.Dot(v1, v2) / PA.Norm(v2) / PA.Norm(v2));
            PointF projected_pt3 = PA.Add(PA.Multiply(PA.Int2Float(v2), scale), pt1);

            return(PA.Float2Int(projected_pt3));
        }
예제 #5
0
        public void ShiftCenterTo(Point pt)
        {
            Point transpt = PA.Subtract(pt, this.center);

            for (int i = 0; i < 4; i++)
            {
                this.corners[i] = PA.Add(this.corners[i], transpt);
            }
            this.center = pt;
        }
예제 #6
0
        public static Point Project2NormalVector(Point pt1, Point pt2, Point pt3)
        {
            /* project a vector v1 formed by pt1-pt3 into the direction of
             * the normal vector of another vector v2 formed by pt1-pt2 */

            // compute the unit normal vector of vector v2
            Point  v2          = PA.Subtract(pt2, pt1);
            float  magnitude   = (float)(PA.Norm(pt1, pt2));
            PointF unit_normal = new PointF(v2.Y / magnitude, -v2.X / magnitude);
            // project v1 into the normal vector
            Point  v1           = PA.Subtract(pt3, pt1);
            PointF projected    = PA.Multiply(unit_normal, (float)PA.Dot(v1, unit_normal));
            PointF projected_v3 = PA.Add(projected, pt1);

            return(PA.Float2Int(projected_v3));
        }
예제 #7
0
        public BoundingBox(Point[] corners, double angle)
        {
            this.corners = new Point[4];
            for (int i = 0; i < 4; i++)
            {
                this.corners[i] = corners[i];
            }
            this.angle = angle;
            // the longer axis is length
            this.length = PA.Norm(corners[0], corners[1]);
            this.width  = PA.Norm(corners[0], corners[3]);
            // compute the center of rotated rect
            int xc = 0, yc = 0;

            for (int i = 0; i < 4; i++)
            {
                xc += this.corners[i].X;
                yc += this.corners[i].Y;
            }
            this.center = new Point(xc / 4, yc / 4);
        }
예제 #8
0
        private Point[] reOderPoints(Point[] pts)
        {
            Point[] ordered_pts = new Point[4];
            int     ind         = 0;
            var     inds        = pts.Select((pt, i) => new KeyValuePair <int, int>(i, pt.Y))
                                  .OrderBy(x => x.Value).Select(x => x.Key).ToArray();

            if ((pts[inds[0]].Y == pts[inds[1]].Y) && (pts[inds[0]].X > pts[inds[1]].X))
            {
                ind = inds[1];
            }
            else
            {
                ind = inds[0];
            }
            double dis1 = PA.Norm(pts[ind], pts[(ind + 1) % 4]);
            double dis2 = PA.Norm(pts[ind], pts[(ind + 3) % 4]);

            ordered_pts[1] = dis1 >= dis2 ? pts[(ind + 1) % 4] : pts[(ind + 3) % 4];
            ordered_pts[3] = dis1 < dis2 ? pts[(ind + 1) % 4] : pts[(ind + 3) % 4];
            ordered_pts[0] = pts[ind];
            ordered_pts[2] = pts[(ind + 2) % 4];
            return(ordered_pts);
        }
예제 #9
0
        public void ShiftDirection(int ind, int step = 3)
        {
            // ind = 0 --> move left
            // ind = 1 --> move right
            // ind = 2 --> move up
            // ind = 3 --> move down
            Point transpt = new Point(0, 0);

            switch (ind)
            {
            case 0: transpt = new Point(-step, 0); break;

            case 1: transpt = new Point(step, 0); break;

            case 2: transpt = new Point(0, -step); break;

            case 3: transpt = new Point(0, step); break;
            }
            for (int i = 0; i < 4; i++)
            {
                this.corners[i] = PA.Add(this.corners[i], transpt);
            }
            this.center = PA.Add(this.center, transpt);
        }
예제 #10
0
        public static double Norm(Point pt1, Point pt2)
        {
            double length = PA.Norm(PA.Subtract(pt1, pt2));

            return(length);
        }