private Point2 binarySeachPoint(Point2 from, double angle, int distToNextPoint, double shift_delta)
        {
            double high = distToNextPoint;
            double low  = 0;

            double eps = 1e-3;

            Point2 to = null;

            while (high - low > eps)
            {
                double current = (low + high) / 2;

                to = new Point2(from.X + (float)(current * Math.Cos(angle)), from.Y + (float)(current * Math.Sin(angle)));
                var mid = new Point2((to.X + from.X) / 2, (to.Y + from.Y) / 2);
                mid.X += (float)(shift_delta * Math.Sin(angle));
                mid.Y += (float)(shift_delta * Math.Cos(angle));
                if (!PatternGenerator.checkCoordinateLimits(mid))
                {
                    mid.X -= 2 * (float)(shift_delta * Math.Sin(angle));
                    mid.Y -= 2 * (float)(shift_delta * Math.Cos(angle));
                }

                double spacing = calcCircleSegmentLength(from, to, mid);

                if (spacing < distToNextPoint)
                {
                    low = current;
                }
                else
                {
                    high = current;
                }
            }

            return(to);
        }
Пример #2
0
        public List <CircleObject> generatePolygons(MapContextAwareness mapContext, int points, int number, int spacing, int rotation, int shift, bool randomize)
        {
            var result = new List <CircleObject>();

            double angle = 0;
            int    X     = mapContext.X;
            int    Y     = mapContext.Y;

            int shiftx = shift;
            int shifty = shift;

            for (int i = 0; i < number && mapContext.Offset < mapContext.endOffset; ++i)
            {
                Point2 pp = checkPolygonialBounds(X, Y, spacing);

                if (!ReferenceEquals(pp, null))
                {
                    X = (int)pp.X;
                    Y = (int)pp.Y;
                }

                var ps = PatternGenerator.polygon(points, new Point2(X, Y), spacing, angle);

                if (randomize)
                {
                    //ps = PatternGenerator.shuffleOrder(ps);
                    ps = reoderIntoStar(ps);
                }

                foreach (var p in ps)
                {
                    p.Type = BMAPI.v1.HitObjectType.Circle;
                }
                ps[0].Type |= BMAPI.v1.HitObjectType.NewCombo;

                foreach (var obj in ps)
                {
                    obj.StartTime      = (int)mapContext.Offset;
                    mapContext.Offset += mapContext.bpm;
                }

                result.AddRange(ps);
                angle += PatternGenerator.ConvertToRadians(rotation);
                if (!PatternGenerator.checkCoordinateLimits(X, Y, points, spacing, shiftx, shifty))
                {
                    //TODO: add normalization
                    Point2 next = PatternGenerator.findNextPosition(X, Y, shift);
                    shiftx = (int)(next.X - X);
                    shifty = (int)(next.Y - Y);
                }
                X += shiftx;
                Y += shifty;
            }

            double nextShift    = Math.Sqrt(2 * spacing * spacing * (1.0 - Math.Cos(Math.PI * 2 / points)));
            Point2 nextPosition = PatternGenerator.findNextPosition(X, Y, nextShift);

            mapContext.X = (int)nextPosition.X;
            mapContext.Y = (int)nextPosition.Y;

            return(result);
        }
 private bool checkNextJumpBounds(int X, int Y, double angle)
 {
     return(!PatternGenerator.checkCoordinateLimits(X, Y) && !ReferenceEquals(checkVerticalJumpBounds(X, Y, spacing, angle), null));
 }
        public List <CircleObject> generateStreams(MapContextAwareness mapContext, int points, int number, int spacing, int shift)
        {
            //spacing is the distance between two notes in the stream

            if (end)
            {
                //double endOffset = mapContext.endOffset;
                //double currOffset = mapContext.Offset;

                //int n = (int)Math.Floor((endOffset - currOffset) / mapContext.bpm * 2 / points) - 1;

                number = (int)1e6;
            }

            List <CircleObject> result = new List <CircleObject>();

            int shiftx = shift;
            int shifty = shift;

            double angle = 0;
            bool   flag  = false;

            int distToNextPoint = spacing * (points - 1);

            for (int i = 0; i < number && mapContext.Offset < mapContext.endOffset; ++i)
            {
                Point2 from      = new Point2(mapContext.X, mapContext.Y);
                double tmp_angle = angle;
                Point2 to        = new Point2(from.X + distToNextPoint * (float)Math.Cos(angle), from.Y + distToNextPoint * (float)Math.Sin(angle));
                if (!PatternGenerator.checkCoordinateLimits(to))
                {
                    flag = true;
                }

                int tmp_spacing = distToNextPoint;
                for (int k = 0; flag; ++k)
                {
                    tmp_angle = Utils.rng.NextDouble() * Math.PI * 2;
                    while (Math.Abs(Math.Tan(angle) - Math.Tan(tmp_angle)) < 0.05)
                    {
                        tmp_angle = Utils.rng.NextDouble() * Math.PI * 2;
                    }

                    to = new Point2(from.X + tmp_spacing * (float)Math.Cos(tmp_angle), from.Y + tmp_spacing * (float)Math.Sin(tmp_angle));

                    if (PatternGenerator.checkCoordinateLimits(to))
                    {
                        flag = false;
                    }
                    else
                    {
                        if (k > 1000)
                        {
                            to          = pointToCenter(from, tmp_spacing);
                            tmp_spacing = (int)(tmp_spacing * 0.9);
                            k           = 0;
                        }
                    }
                }

                double mid_delta = generateMidDelta();

                List <CircleObject> pattern = null;

                if (mid_delta > 0.1)
                {
                    double shift_delta = mid_delta * distToNextPoint;
                    to = binarySeachPoint(from, tmp_angle, distToNextPoint, shift_delta);

                    var mid = new Point2((to.X + from.X) / 2, (to.Y + from.Y) / 2);
                    mid.X += (float)(shift_delta * Math.Sin(tmp_angle));
                    mid.Y += (float)(shift_delta * Math.Cos(tmp_angle));
                    if (!PatternGenerator.checkCoordinateLimits(mid))
                    {
                        mid.X -= 2 * (float)(shift_delta * Math.Sin(tmp_angle));
                        mid.Y -= 2 * (float)(shift_delta * Math.Cos(tmp_angle));
                    }
                    pattern = PatternGenerator.stream(points, from, to, mid);
                }
                else
                {
                    pattern = PatternGenerator.stream(points, from, to);
                }
                pattern[0].Type |= BMAPI.v1.HitObjectType.NewCombo;
                foreach (var obj in pattern)
                {
                    obj.StartTime      = (int)mapContext.Offset;
                    mapContext.Offset += mapContext.bpm / 2;
                }

                result.AddRange(pattern);

                double spacing_shift     = spacing;
                double recommended_shift = Math.Max(spacing_shift, shift);

                if (!PatternGenerator.checkCoordinateLimits(to.X + shiftx, to.Y + shifty))
                {
                    Point2 next = PatternGenerator.findNextPosition(mapContext.X, mapContext.Y, recommended_shift);
                    shiftx = (int)(next.X - mapContext.X);
                    shifty = (int)(next.Y - mapContext.Y);

                    double norm = Math.Sqrt(Utils.sqr(shiftx) + Utils.sqr(shifty));

                    if (norm < 0.1)
                    {
                        norm = 1;
                    }

                    shiftx = (int)(shiftx / norm * recommended_shift);
                    shifty = (int)(shifty / norm * recommended_shift);
                }

                mapContext.X = (int)to.X + shiftx;
                mapContext.Y = (int)to.Y + shifty;

                angle = tmp_angle;
            }

            return(result);
        }