Example #1
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;
            }
        }
Example #2
0
        public TracingConfiguration(BaseScalarField priorityField, BaseScalarField separationField, ITensorField tensorField, IValueGenerator roadWidth,
                                    float searchAngle   = 0.3926991f, //22.5 degrees in radians
                                    float segmentLength = 10,
                                    float mergeDistance = 25
                                    )
        {
            Contract.Requires(priorityField != null);
            Contract.Requires(separationField != null);
            Contract.Requires(tensorField != null);
            Contract.Requires(roadWidth != null);

            _priorityField          = priorityField;
            _separationField        = separationField;
            _tensorField            = tensorField;
            _roadWidth              = roadWidth;
            _consineSearchConeAngle = (float)Math.Cos(searchAngle);
            _segmentLength          = segmentLength;
            _mergeDistance          = mergeDistance;
        }
Example #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);
        }
Example #4
0
        public Heightmap(BaseScalarField height)
        {
            Contract.Requires(height != null);

            _gradient = new Gradient(height);
        }
Example #5
0
        private static void AddSeed(IMinHeap <KeyValuePair <float, Seed> > seeds, Seed seed, BaseScalarField priority = null, BaseScalarField separation = null)
        {
            Contract.Requires(seeds != null);

            var prio = priority.SafeSample(seed.Point)
                       + 1 / separation.SafeSample(seed.Point);

            seeds.Add(new KeyValuePair <float, Seed>(-prio, seed));
        }
Example #6
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);
        }
Example #7
0
        private void Build(IEnumerable <Seed> initialSeeds, Vector2 min, Vector2 max, BaseScalarField separation, bool forward, bool backward, float maxSegmentLength, float mergeDistance, float cosineSearchAngle, Func <Vector2, bool> isOutOfBounds, Func <Edge, bool> edgeFilter, Action <Streamline> streamCreated)
        {
            Contract.Requires(initialSeeds != null);
            Contract.Requires(separation != null);
            Contract.Requires(isOutOfBounds != null);
            Contract.Requires(streamCreated != null);

            var seeds = new MinHeap <KeyValuePair <float, Seed> >(1024, new KeyComparer <float, Seed>());

            foreach (var initialSeed in initialSeeds)
            {
                AddSeed(seeds, initialSeed);
            }

            //Trace out roads for every single seed
            while (seeds.Count > 0)
            {
                var s = RemoveSeed(seeds, separation, cosineSearchAngle, edgeFilter);
                if (!s.HasValue)
                {
                    continue;
                }

                if (forward)
                {
                    var stream = CheckStream(Trace(s.Value, false, seeds, isOutOfBounds, maxSegmentLength, mergeDistance, cosineSearchAngle, separation));
                    if (stream != null)
                    {
                        _streams.Add(stream);
                        streamCreated(stream);
                    }
                }

                if (backward)
                {
                    var stream = CheckStream(Trace(s.Value, true, seeds, isOutOfBounds, maxSegmentLength, mergeDistance, cosineSearchAngle, separation));
                    if (stream != null)
                    {
                        _streams.Add(stream);
                        streamCreated(stream);
                    }
                }
            }
        }
Example #8
0
        public Gradient(BaseScalarField scalar)
        {
            Contract.Requires(scalar != null);

            _scalar = scalar;
        }