Example #1
0
        /**
         * Attempts to translate, rotate, and scale @points to match @target as closely as possible.
         * Only points[0, target.Length] coordinates are used in the matching process - points[target.Length, points.Length]
         * are just along for the ride.
         */
        public static pb_Transform2D MatchCoordinates(Vector2[] points, Vector2[] target)
        {
            int length = points.Length < target.Length ? points.Length : target.Length;

            pb_Bounds2D t_bounds = new pb_Bounds2D(target, length);     // only match the bounds of known matching points

            // move points to the center of target
            Vector2 translation = t_bounds.center - pb_Bounds2D.Center(points, length);

            Vector2[] transformed = new Vector2[points.Length];
            for (int i = 0; i < points.Length; i++)
            {
                transformed[i] = points[i] + translation;
            }

            // rotate to match target points
            Vector2 target_angle = target[1] - target[0], transform_angle = transformed[1] - transformed[0];

            float angle = Vector2.Angle(target_angle, transform_angle);
            float dot   = Vector2.Dot(pb_Math.Perpendicular(target_angle), transform_angle);

            if (dot < 0)
            {
                angle = 360f - angle;
            }

            for (int i = 0; i < points.Length; i++)
            {
                transformed[i] = transformed[i].RotateAroundPoint(t_bounds.center, angle);
            }

            // and lastly scale
            pb_Bounds2D p_bounds = new pb_Bounds2D(transformed, length);
            Vector2     scale    = t_bounds.size.DivideBy(p_bounds.size);

            // for(int i = 0; i < points.Length; i++)
            //  transformed[i] = transformed[i].ScaleAroundPoint(t_bounds.center, scale);

            return(new pb_Transform2D(translation, angle, scale));
        }
Example #2
0
        /**
         * Returns true if the polygon contains point.  False otherwise.
         * Casts a ray from outside the bounds to the polygon and checks how
         * many edges are hit.
         * @param polygon A series of individual edges composing a polygon.  polygon length *must* be divisible by 2.
         * This overload accepts an array of points and an array of indices that compose the polygon.
         */
        public static bool PointInPolygon(Vector2[] polygon, int[] indices, Vector2 point)
        {
            pb_Bounds2D bounds = new pb_Bounds2D(polygon, indices);

            if (bounds.ContainsPoint(point))
            {
                Vector2 rayStart   = bounds.center + Vector2.up * (bounds.size.y + 2f);
                int     collisions = 0;

                for (int i = 0; i < polygon.Length; i += 2)
                {
                    if (GetLineSegmentIntersect(rayStart, point, polygon[indices[i]], polygon[indices[i + 1]]))
                    {
                        collisions++;
                    }
                }

                return(collisions % 2 != 0);
            }
            else
            {
                return(false);
            }
        }
Example #3
0
    public static bool GeneratePolygonCrosshatch(Vector2[] polygon, float scale, Color color, int lineSpacing, ref Texture2D texture)
        #endif
    {
                #if PB_DEBUG
        profiler.BeginSample("GeneratePolygonCrosshatch");
                #endif

        pb_Bounds2D bounds = new pb_Bounds2D(polygon);

        Vector2 offset = bounds.center - bounds.extents;

        /// shift polygon to origin 0,0
        for (int i = 0; i < polygon.Length; i++)
        {
            polygon[i] -= offset;
            polygon[i] *= scale;
        }

        bounds.center -= offset;
        bounds.size   *= scale;

        int width  = (int)(bounds.size.x);
        int height = (int)(bounds.size.y);

        if (width <= 0 || height <= 0)
        {
            return(false);
        }

                #if PB_DEBUG
        profiler.BeginSample("Allocate Texture");
                #endif

        if (texture == null)
        {
            texture            = new Texture2D(width, height, TextureFormat.ARGB32, false);
            texture.filterMode = FilterMode.Point;
            texture.wrapMode   = TextureWrapMode.Clamp;
        }
        else
        {
            if (texture.width != width || texture.height != height)
            {
                texture.Resize(width, height, TextureFormat.ARGB32, false);
            }
        }

                #if PB_DEBUG
        profiler.EndSample();
        profiler.BeginSample("Fill Clear");
                #endif

        Color[]    colors     = new Color[width * height];
        List <int> intersects = new List <int>();

        for (int i = 0; i < width * height; i++)
        {
            colors[i] = Color.clear;
        }

                #if PB_DEBUG
        profiler.EndSample();
                #endif

        /**
         *	Horizontal lines
         */
        for (int h = 0; h < height / lineSpacing; h++)
        {
            int y = (h * lineSpacing);
            intersects.Clear();

                        #if PB_DEBUG
            profiler.BeginSample("Find Intersections");
                        #endif

            Vector2 start = new Vector2(bounds.center.x - bounds.size.x, y);
            Vector2 end   = new Vector2(bounds.center.x + bounds.size.x, y);

            for (int i = 0; i < polygon.Length; i += 2)
            {
                Vector2 intersect = Vector2.zero;

                if (pb_Math.GetLineSegmentIntersect(polygon[i], polygon[i + 1], start, end, ref intersect))
                {
                    intersects.Add((int)intersect.x);
                }
            }

            intersects = intersects.Distinct().ToList();
            intersects.Sort();

                        #if PB_DEBUG
            profiler.EndSample();
            profiler.BeginSample("Fill Color");
                        #endif

            for (int i = 0; i < intersects.Count - 1; i++)
            {
                // can't just use Dot product because we the winding order isn't consistent
                if (pb_Math.PointInPolygon(polygon, new Vector2(intersects[i] + 2, y)))
                {
                    for (int n = intersects[i]; n < intersects[i + 1]; n++)
                    {
                        colors[((height - 1) - y) * width + n] = color;
                    }
                }
            }

                        #if PB_DEBUG
            profiler.EndSample();
                        #endif
        }

        /**
         *	Vertical lines
         */
        if (lineSpacing > 1)
        {
            for (int w = 0; w < width / lineSpacing; w++)
            {
                int x = (w * lineSpacing);

                intersects.Clear();

                Vector2 start = new Vector2(x, bounds.center.y - bounds.size.y);
                Vector2 end   = new Vector2(x, bounds.center.y + bounds.size.y);

                for (int i = 0; i < polygon.Length; i += 2)
                {
                    Vector2 intersect = Vector2.zero;
                    if (pb_Math.GetLineSegmentIntersect(polygon[i], polygon[i + 1], start, end, ref intersect))
                    {
                        intersects.Add((int)intersect.y);
                    }
                }

                intersects = intersects.Distinct().ToList();
                intersects.Sort();

                for (int i = 0; i < intersects.Count - 1; i++)
                {
                    if (pb_Math.PointInPolygon(polygon, new Vector2(x, intersects[i] + 2)))
                    {
                        for (int y = intersects[i]; y < intersects[i + 1]; y++)
                        {
                            colors[((height - 1) - y) * width + x] = color;
                        }
                    }
                }
            }
        }

                #if PB_DEBUG
        profiler.BeginSample("SetPixels");
                #endif

        texture.SetPixels(colors);
        texture.Apply(false);

                #if PB_DEBUG
        profiler.EndSample();
        profiler.EndSample();
                #endif

        return(true);
    }