Exemple #1
0
        private void AnchorsOnAnchorsChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            if (_ignoreAnchorsChange)
            {
                return;
            }

            var anchor = (Anchor)sender;

            // Correct the anchor change if it resulted in a speed limit violation
            if (PrevOverSpeedLimit(anchor) || NextOverSpeedLimit(anchor))
            {
                _ignoreAnchorsChange      = true;
                Graph.IgnoreAnchorUpdates = true;

                // Use binary search to find the closest value to the limit
                const double d = 0.001;

                switch (e.NewValue)
                {
                case double newDouble:
                    var oldDouble = (double)e.OldValue;

                    // Test if the old value is also a illegal speed violation
                    anchor.SetValue(e.Property, oldDouble);
                    if (PrevOverSpeedLimit(anchor) || NextOverSpeedLimit(anchor))
                    {
                        anchor.SetValue(e.Property, newDouble);
                        break;
                    }

                    anchor.SetValue(e.Property, BinarySearchUtil.DoubleBinarySearch(
                                        oldDouble, newDouble, d,
                                        mid => {
                        anchor.SetValue(e.Property, mid);
                        return(!PrevOverSpeedLimit(anchor) && !NextOverSpeedLimit(anchor));
                    }));
                    break;

                case Vector2 newVector2:
                    if (ViewModel.GraphModeSetting == SlideratorVm.GraphMode.Position && anchor.PreviousAnchor != null)
                    {
                        // List of bounds. X represents the minimum Y value and Y represents the maximum Y value
                        // I use Vector2 here because it has useful math methods
                        var bounds = new List <Vector2>();

                        if (anchor.PreviousAnchor != null)
                        {
                            var maxSpeed = InterpolatorHelper.GetBiggestDerivative(anchor.Interpolator);

                            if (Math.Abs(newVector2.X - anchor.PreviousAnchor.Pos.X) < Precision.DOUBLE_EPSILON)
                            {
                                bounds.Add(new Vector2(anchor.PreviousAnchor.Pos.Y));
                            }
                            else
                            {
                                bounds.Add(new Vector2(anchor.PreviousAnchor.Pos.Y) +
                                           new Vector2(Precision.DOUBLE_EPSILON).PerpendicularRight +
                                           new Vector2(ViewModel.VelocityLimit * ViewModel.SvGraphMultiplier *
                                                       (newVector2.X - anchor.PreviousAnchor.Pos.X) / maxSpeed)
                                           .PerpendicularLeft);
                            }
                        }

                        if (anchor.NextAnchor != null)
                        {
                            var maxSpeed = InterpolatorHelper.GetBiggestDerivative(anchor.NextAnchor.Interpolator);

                            if (Math.Abs(newVector2.X - anchor.NextAnchor.Pos.X) < Precision.DOUBLE_EPSILON)
                            {
                                bounds.Add(new Vector2(anchor.NextAnchor.Pos.Y));
                            }
                            else
                            {
                                bounds.Add(new Vector2(anchor.NextAnchor.Pos.Y) +
                                           new Vector2(Precision.DOUBLE_EPSILON).PerpendicularRight +
                                           new Vector2(ViewModel.VelocityLimit * ViewModel.SvGraphMultiplier *
                                                       (newVector2.X - anchor.NextAnchor.Pos.X) / maxSpeed)
                                           .PerpendicularRight);
                            }
                        }

                        // Clamp the new Y value between all the bounds
                        var newY = bounds.Aggregate(newVector2.Y,
                                                    (current, bound) => MathHelper.Clamp(current, bound.X, bound.Y));

                        // Break if the resulting value is not inside all the bounds
                        if (!bounds.All(b => newY >= b.X && newY <= b.Y))
                        {
                            break;
                        }

                        anchor.SetValue(e.Property, new Vector2(newVector2.X, newY));
                    }

                    break;
                }

                _ignoreAnchorsChange      = false;
                Graph.IgnoreAnchorUpdates = false;
            }

            if (ViewModel.PixelLength < HitObjectElement.MaxPixelLength)
            {
                AnimateProgress(GraphHitObjectElement);
            }
            UpdatePointsOfInterest();
            UpdateVelocity();
        }
Exemple #2
0
        private void GenerateDendrites()
        {
            double leftovers = 0;

            //double totalDendriteToAddLength = 0;
            foreach (var neuron in _slider.Where(n => n.Terminal != null))
            {
                // Find angles for the neuron and the terminal to point the dendrites towards
                var dir = Math.Sign(neuron.Terminal.Nucleus.PathPosition - neuron.Nucleus.PathPosition);
                dir = dir == 0 ? 1 : dir;  // Let dir not be zero

                var dendriteDir1 = dir * NearbyNonZeroDiff(neuron.Nucleus.SegmentIndex).Normalized();
                var dendriteDir2 = -dir *NearbyNonZeroDiff(neuron.Terminal.Nucleus.SegmentIndex).Normalized();

                // Do an even split of dendrites between this neuron and the terminal
                var dendriteToAdd = neuron.DendriteLength + leftovers;

                // Find the time at which the position function goes in between the neuron and the terminal
                var width      = neuron.Terminal.Time - neuron.Time;
                var axonWidth  = neuron.AxonLenth / Velocity;
                var middleTime = BinarySearchUtil.DoubleBinarySearch(neuron.Time, neuron.Terminal.Time, 0.01,
                                                                     d => PositionFunction(d) <= (neuron.Nucleus.PathPosition + neuron.Terminal.Nucleus.PathPosition) / 2);

                // Calculate the distribution of dendrites to let the axon pass through the middle at the same time as the position funciton does
                var leftPortion  = MathHelper.Clamp((2 * (middleTime - neuron.Time) - axonWidth) / (2 * (width - axonWidth)), 0, 1);
                var rightPortion = 1 - leftPortion;

                var dendriteToAddLeft  = dendriteToAdd * leftPortion;
                var dendriteToAddRight = dendriteToAdd * rightPortion;

                //totalDendriteToAddLength += dendriteToAddLeft;
                //totalDendriteToAddLength += dendriteToAddRight;

                // Get the speeds at the times of the dendrites to give the dendrites appriopriate lengths to the speed at the time
                var speedLeft  = GetSpeedAtTime(neuron.Time + dendriteToAddLeft / Velocity / 2, 0.01);
                var speedRight = GetSpeedAtTime(neuron.Terminal.Time - dendriteToAddRight / Velocity / 2, 0.01);

                //Console.WriteLine($@"Adding {dendriteToAddLeft + dendriteToAddRight} length to dendrites!");
                //var beforeLength = neuron.Dendrites.Sum(d => d.Length) + neuron.Terminal.Dendrites.Sum(d => d.Length);

                dendriteToAddRight += AddDendriteLength(neuron, dendriteToAddLeft, dendriteDir1, MinDendriteLength, 4 * Math.Pow(speedLeft * 2, 2));
                leftovers           = AddDendriteLength(neuron.Terminal, dendriteToAddRight, dendriteDir2, MinDendriteLength, 4 * Math.Pow(speedRight * 2, 2));

                //var afterLength = neuron.Dendrites.Sum(d => d.Length) + neuron.Terminal.Dendrites.Sum(d => d.Length);
                //Console.WriteLine($@"Actually added {afterLength - beforeLength} length to dendrites and got {leftovers} leftover!");
            }

            /*double actualLength = 0;
             * double wantedLength = 0;
             * double axonLength = 0;
             * double dendriteLength = 0;
             * foreach (var n in _slider) {
             *  actualLength += n.AxonLenth + n.Dendrites.Sum(d => d.Length);
             *  wantedLength += n.WantedLength;
             *  axonLength += n.AxonLenth;
             *  dendriteLength += n.DendriteLength;
             * }
             * Console.WriteLine("Path length: " + actualLength);
             * Console.WriteLine("Wanted length: " + wantedLength);
             * Console.WriteLine("Axon length: " + axonLength);
             * Console.WriteLine("Dendrite length: " + dendriteLength);
             * Console.WriteLine("DendriteToAdd length: " + totalDendriteToAddLength);*/
        }