예제 #1
0
        /// <summary>
        /// Scale the multi stroke so that it can fit into predefined bounding box
        /// </summary>
        public void Scale()
        {
            float minx = float.MaxValue, miny = float.MaxValue, maxx = float.MinValue, maxy = float.MinValue;

            for (int i = 0; i < this.Points.Length; i++)
            {
                if (minx > this.Points[i].Point.x)
                {
                    minx = this.Points[i].Point.x;
                }
                if (miny > this.Points[i].Point.y)
                {
                    miny = this.Points[i].Point.y;
                }
                if (maxx < this.Points[i].Point.x)
                {
                    maxx = this.Points[i].Point.x;
                }
                if (maxy < this.Points[i].Point.y)
                {
                    maxy = this.Points[i].Point.y;
                }
            }

            MultiStrokePoint[] scaledPoints = new MultiStrokePoint[this.Points.Length];
            float scale = Math.Max(maxx - minx, maxy - miny);

            for (int i = 0; i < this.Points.Length; i++)
            {
                scaledPoints[i] = new MultiStrokePoint((this.Points[i].Point.x - minx) / scale, (this.Points[i].Point.y - miny) / scale, this.Points[i].StrokeID);
            }

            this.Points = scaledPoints;
        }
예제 #2
0
        /// <summary>
        /// Resample the point list so that the list has NUMBER_OF_POINTS number of points
        /// and points are equidistant to each other.
        ///
        /// First calculate the length of the path. Divided it by (numberOfPoints - 1)
        /// to find the increment. Step through the path, and if the distance covered is
        /// equal to or greater than the increment add a new point to the list by lineer
        /// interpolation.
        /// </summary>
        public void Resample()
        {
            MultiStrokePoint[] resampledPoints = new MultiStrokePoint[NUMBER_OF_POINTS];
            resampledPoints[0] = new MultiStrokePoint(this.Points[0].Point, this.Points[0].StrokeID);
            int n = 1;

            float increment       = GetPathLength() / (NUMBER_OF_POINTS - 1);
            float distanceCovered = 0;

            for (int i = 1; i < this.Points.Length; i++)
            {
                if (this.Points[i].StrokeID == this.Points[i - 1].StrokeID)
                {
                    float distance = Vector2.Distance(this.Points[i - 1].Point, this.Points[i].Point);

                    if (distanceCovered + distance >= increment)
                    {
                        MultiStrokePoint firstPoint = this.Points[i - 1];

                        while (distanceCovered + distance >= increment)
                        {
                            float t = Mathf.Min(Mathf.Max((increment - distanceCovered) / distance, 0.0f), 1.0f);

                            if (float.IsNaN(t))
                            {
                                t = 0.5f;
                            }

                            resampledPoints[n++] = new MultiStrokePoint(
                                (1.0f - t) * firstPoint.Point.x + t * this.Points[i].Point.x,
                                (1.0f - t) * firstPoint.Point.y + t * this.Points[i].Point.y,
                                this.Points[i].StrokeID
                                );

                            distance        = distanceCovered + distance - increment;
                            distanceCovered = 0;
                            firstPoint      = resampledPoints[n - 1];
                        }

                        distanceCovered = distance;
                    }
                    else
                    {
                        distanceCovered += distance;
                    }
                }
            }

            if (n == NUMBER_OF_POINTS - 1)
            {
                resampledPoints[n++] = new MultiStrokePoint(
                    this.Points[this.Points.Length - 1].Point.x,
                    this.Points[this.Points.Length - 1].Point.y,
                    this.Points[this.Points.Length - 1].StrokeID
                    );
            }

            this.Points = resampledPoints;
        }
예제 #3
0
 public MultiStroke(MultiStrokePoint[] points, string name = "")
 {
     this.Name = name;
     this.Points = points;
     this.Scale();
     this.TranslateToCenter();
     this.Resample();
 }
예제 #4
0
        /// <summary>
        /// Move the multi stroke to the center
        /// </summary>
        /// <param name="point">Points to move</param>
        /// <returns>List of moved points</returns>
        public void TranslateToCenter()
        {
            Vector2 p = this.GetCenter();

            MultiStrokePoint[] translatedPoints = new MultiStrokePoint[this.Points.Length];

            for (int i = 0; i < this.Points.Length; i++)
            {
                translatedPoints[i] = new MultiStrokePoint(this.Points[i].Point.x - p.x, this.Points[i].Point.y - p.y, this.Points[i].StrokeID);
            }

            this.Points = translatedPoints;
        }
예제 #5
0
        private static float GreedyCloudMatch(MultiStrokePoint[] points1, MultiStrokePoint[] points2)
        {
            float e = 0.5f;
            int step = Mathf.FloorToInt(Mathf.Pow(points1.Length, 1.0f - e));
            float minDistance = float.MaxValue;

            for (int i = 0; i < points1.Length; i += step) {
                float distance1 = CloudDistance(points1, points2, i);
                float distance2 = CloudDistance(points2, points1, i);
                minDistance = Mathf.Min(minDistance, Mathf.Min(distance1, distance2));
            }
            return minDistance;
        }
예제 #6
0
        private static float CloudDistance(MultiStrokePoint[] points1, MultiStrokePoint[] points2, int startIndex)
        {
            bool[] matched = new bool[points1.Length];
            Array.Clear(matched, 0, points1.Length);

            float sum = 0;
            int i = startIndex;

            do {
                int index = -1;
                float minDistance = float.MaxValue;

                for (int j = 0; j < points1.Length; j++) {
                    if (!matched[j]) {
                        float distance = Vector2.Distance(points1[i].Point, points2[j].Point);
                        if (distance < minDistance) {
                            minDistance = distance;
                            index = j;
                        }
                    }
                }

                matched[index] = true;
                float weight = 1.0f - ((i - startIndex + points1.Length) % points1.Length) / (1.0f * points1.Length);
                sum += weight * minDistance;
                i = (i + 1) % points1.Length;

            } while (i != startIndex);

            return sum;
        }
예제 #7
0
        /// <summary>
        /// Move the multi stroke to the center
        /// </summary>
        /// <param name="point">Points to move</param>
        /// <returns>List of moved points</returns>
        public void TranslateToCenter()
        {
            Vector2 p = this.GetCenter();
            MultiStrokePoint[] translatedPoints = new MultiStrokePoint[this.Points.Length];

            for (int i = 0; i < this.Points.Length; i++) {
                translatedPoints[i] = new MultiStrokePoint(this.Points[i].Point.x - p.x, this.Points[i].Point.y - p.y, this.Points[i].StrokeID);
            }

            this.Points = translatedPoints;
        }
예제 #8
0
        /// <summary>
        /// Scale the multi stroke so that it can fit into predefined bounding box 
        /// </summary>
        public void Scale()
        {
            float minx = float.MaxValue, miny = float.MaxValue, maxx = float.MinValue, maxy = float.MinValue;
            for (int i = 0; i < this.Points.Length; i++) {
                if (minx > this.Points[i].Point.x) minx = this.Points[i].Point.x;
                if (miny > this.Points[i].Point.y) miny = this.Points[i].Point.y;
                if (maxx < this.Points[i].Point.x) maxx = this.Points[i].Point.x;
                if (maxy < this.Points[i].Point.y) maxy = this.Points[i].Point.y;
            }

            MultiStrokePoint[] scaledPoints = new MultiStrokePoint[this.Points.Length];
            float scale = Math.Max(maxx - minx, maxy - miny);

            for (int i = 0; i < this.Points.Length; i++) {
                scaledPoints[i] = new MultiStrokePoint((this.Points[i].Point.x - minx) / scale, (this.Points[i].Point.y - miny) / scale, this.Points[i].StrokeID);
            }

            this.Points = scaledPoints;
        }
예제 #9
0
        /// <summary>
        /// Resample the point list so that the list has NUMBER_OF_POINTS number of points
        /// and points are equidistant to each other.
        /// 
        /// First calculate the length of the path. Divided it by (numberOfPoints - 1)
        /// to find the increment. Step through the path, and if the distance covered is
        /// equal to or greater than the increment add a new point to the list by lineer
        /// interpolation.
        /// </summary>
        public void Resample()
        {
            MultiStrokePoint[] resampledPoints = new MultiStrokePoint[NUMBER_OF_POINTS];
            resampledPoints[0] = new MultiStrokePoint(this.Points[0].Point, this.Points[0].StrokeID);
            int n = 1;

            float increment = GetPathLength() / (NUMBER_OF_POINTS - 1);
            float distanceCovered = 0;

            for (int i = 1; i < this.Points.Length; i++) {

                if (this.Points[i].StrokeID == this.Points[i - 1].StrokeID) {
                    float distance = Vector2.Distance(this.Points[i - 1].Point, this.Points[i].Point);

                    if (distanceCovered + distance >= increment) {

                        MultiStrokePoint firstPoint = this.Points[i - 1];

                        while (distanceCovered + distance >= increment) {

                            float t = Mathf.Min(Mathf.Max((increment - distanceCovered) / distance, 0.0f), 1.0f);

                            if (float.IsNaN(t)) t = 0.5f;

                            resampledPoints[n++] = new MultiStrokePoint(
                                (1.0f - t) * firstPoint.Point.x + t * this.Points[i].Point.x,
                                (1.0f - t) * firstPoint.Point.y + t * this.Points[i].Point.y,
                                this.Points[i].StrokeID
                            );

                            distance = distanceCovered + distance - increment;
                            distanceCovered = 0;
                            firstPoint = resampledPoints[n - 1];
                        }

                        distanceCovered = distance;

                    } else distanceCovered += distance;
                }
            }

            if (n == NUMBER_OF_POINTS - 1) {
                resampledPoints[n++] = new MultiStrokePoint(
                    this.Points[this.Points.Length - 1].Point.x,
                    this.Points[this.Points.Length - 1].Point.y,
                    this.Points[this.Points.Length - 1].StrokeID
                );
            }

            this.Points = resampledPoints;
        }