示例#1
0
        public Vector2 Sample(Vector2 position)
        {
            var v = _scalar.Sample(position);
            var x = _scalar.Sample(new Vector2(position.X + 1, position.Y));
            var y = _scalar.Sample(new Vector2(position.X, position.Y + 1));

            return(new Vector2(
                       v - x,
                       v - y
                       ));
        }
示例#2
0
        private static IEnumerable <Seed> SeedsAlongEdge(Region region, BaseScalarField distanceField, IVector2Field major, IVector2Field minor)
        {
            float   d        = 0;
            Vector2?previous = null;

            foreach (var vertex in region.Vertices)
            {
                if (previous.HasValue)
                {
                    var pos    = previous.Value;
                    var v      = vertex - previous.Value;
                    var length = v.Length();
                    var dir    = v / length;

                    for (int i = 0; i < length; i++)
                    {
                        var separation = distanceField.Sample(pos + dir * i);
                        d += separation;
                        if (d >= separation)
                        {
                            yield return(new Seed(pos + dir * i, major, minor));

                            d -= separation;
                        }
                    }
                }
                previous = vertex;
            }
        }
示例#3
0
        private Seed?RemoveSeed(IMinHeap <KeyValuePair <float, Seed> > seeds, BaseScalarField separation, float cosineSearchAngle, Func <Edge, bool> edgeFilter = null)
        {
            Contract.Requires(seeds != null);
            Contract.Requires(separation != null);

            while (seeds.Count > 0)
            {
                //Get the highest priority seed
                var s = seeds.RemoveMin().Value;

                //Check if it's valid
                var d = s.Field.Sample(s.Point);

                //Degenerate point?
                var l = d.Length();
                if (l < 0.001f)
                {
                    continue;
                }

                var sep = separation.Sample(s.Point);

                //Normalize direction
                d /= l;

                //Get edges near this point and check if there is a parallel edge
                if (FindEdges(s.Point, sep).Where(e => edgeFilter == null || edgeFilter(e)).Any(e => Math.Abs(Vector2.Dot(e.Direction, d)) > cosineSearchAngle))
                {
                    continue;
                }

                return(s);
            }

            //No valid seeds found
            return(null);
        }
示例#4
0
        private Streamline Trace(Seed seed, bool reverse, MinHeap <KeyValuePair <float, Seed> > seeds, Func <Vector2, bool> isOutOfBounds, float maxSegmentLength, float mergeDistance, float cosineSearchAngle, BaseScalarField separation)
        {
            var maxSegmentLengthSquared = maxSegmentLength * maxSegmentLength;

            var seedingDistance = float.MaxValue;
            var direction       = Vector2.Zero;
            var position        = seed.Point;
            var stream          = new Streamline(FindOrCreateVertex(position, mergeDistance, cosineSearchAngle));

            //This is a weird way to do a for loop! What gives?
            //This is, in many respects, a better way to do it if you don't want i to be mutated within the loop
            //In this case I'm using it to pacify a persistent CodeContracts false positive (this loop is too complex for it to analyze, I guess?)
            foreach (var i in Enumerable.Range(0, 10000))
            {
                direction = seed.Field.TraceVectorField(position, direction, maxSegmentLength);
                if (i == 0)
                {
                    direction *= reverse ? -1 : 1;
                }

                //degenerate step check
                var segmentLength = direction.Length();
                if (segmentLength < 0.00005f)
                {
                    break;
                }

                //Excessive step check
                if (segmentLength > maxSegmentLength)
                {
                    direction    /= segmentLength * maxSegmentLength;
                    segmentLength = maxSegmentLength;
                }

                //Step along path
                position        += direction;
                seedingDistance += segmentLength;

                //Bounds check
                if (isOutOfBounds(position))
                {
                    CreateEdge(stream, position, Vector2.Normalize(direction), maxSegmentLength, maxSegmentLengthSquared, mergeDistance, cosineSearchAngle, skipDistanceCheck: true);
                    break;
                }

                //Create the segment and break if it says so
                if (CreateEdge(stream, position, Vector2.Normalize(direction), maxSegmentLength, maxSegmentLengthSquared, mergeDistance, cosineSearchAngle))
                {
                    break;
                }

                //Accumulate seeds to trace into the alternative field
                var seedSeparation = separation.Sample(position);
                if (seedingDistance > seedSeparation)
                {
                    seedingDistance = 0;
                    AddSeed(seeds, new Seed(position, seed.AlternativeField, seed.Field));
                }
            }

            return(stream);
        }