Ejemplo n.º 1
0
        /// <summary>
        /// Cycles through a list of points and creates a fractal
        /// version of the points by splitting each one in half and
        /// moving it a random amount.
        /// </summary>
        /// <returns>A true if at least one point was changed.</returns>
        public static bool StaggerPoints(
			CenterPointList points,
			MersenneRandom random,
			float minimumDistance)
        {
            // Ignores blanks and null
            if (points == null)
                throw new ArgumentException("points cannot be null");

            if (random == null)
                throw new ArgumentException("random cannot be null");

            if (points.Count < 2)
                return false;

            // Go through each set of points
            CenterPointList newPoints = new CenterPointList();
            bool changed = false;

            for (int i = 0; i < points.Count - 1; i++)
            {
                // Get the points
                CenterPoint p1 = points[i];
                CenterPoint p2 = points[i + 1];

                // Add the first point
                newPoints.Add(p1);

                // Get the distance
                float distance = CalculateDistance(p1.Point, p2.Point);

                if (distance > minimumDistance)
                {
                    // These two are far enough to calculate a new point
                    CenterPoint mp =
                        new CenterPoint((p1.X + p2.X) / 2, (p1.Y + p2.Y) / 2);
                    float delta = distance * Constants.FractalDecay;
                    float diff = random.NextSingle(-delta, delta);

                    // Calculate the new point
                    float dy = p2.Y - p1.Y;
                    float dx = p2.X - p1.X;

                    if (dy == 0)
                    {
                        // This is a horizontal line
                        mp.Y += diff;
                    }
                    else if (dx == 0)
                    {
                        // This is a vertical line
                        mp.X += diff;
                    }
                    else
                    {
                        // Figure out the slope of the line
                        double theta1 = Math.Tanh(dy / dx);
                        double theta2 = theta1 - Math.PI / 2;

                        mp.X = (float) (mp.X + diff * Math.Cos(theta2));
                        mp.Y = (float) (mp.Y + diff * Math.Sin(theta2));
                    }

                    // Add the created point
                    newPoints.Add(mp);
                    changed = true;
                }

                // Add the second point
                newPoints.Add(p2);
            }

            // See if we changes something
            if (changed)
            {
                // Swap the points
                points.Clear();
                points.AddAll(newPoints);
                newPoints.Clear();
            }

            // Return our status
            return changed;
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Loops through the points and staggers them repeatedly.
        /// </summary>
        public static void StaggerPoints(
			CenterPointList points,
			MersenneRandom random,
			float minimumDistance,
			int passes)
        {
            // Go through the minimum number of passes
            for (int i = 0; i < passes; i++)
            {
                if (!StaggerPoints(points, random, minimumDistance))
                    break;
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Creates a segment from a child junction to its parent.
        /// </summary>
        public Segment Create(
			Junction child, PointF childPoint, double distance)
        {
            // Sanity checking
            if (child.ParentJunction == null)
                throw new Exception("Cannot generate with a null parent");

            // Get the distance between the two points
            Segment segment = new Segment();
            Junction parent = child.ParentJunction;

            // Add the two end points
            CenterPointList points = new CenterPointList();
            points.Add(new CenterPoint(0, 0));
            points.Add(new CenterPoint(childPoint));

            // Split apart the line
            #if DEBUG
            Stopwatch stopwatch = Stopwatch.StartNew();
            #endif

            // Stagger (fractalize) the points
            Geometry.StaggerPoints(points, parent.Random,
                Constants.MinimumSegmentDistance,
                Constants.StaggerSegmentPasses);

            #if DEBUG
            // Show timing information
            stopwatch.Stop();
            Log.Debug("Fractal Time: {0}", stopwatch.Elapsed);
            stopwatch.Reset();
            stopwatch.Start();
            #endif

            // Once we generated a set of center points, we go through
            // and add a randomly-sized and angled square to each
            // point, unioning the results to get the shape of the
            // entire segment.
            IPoly shape = null;
            float log = 0;

            if (distance > 0)
                log = (float) Math.Log(distance) * 10;

            foreach (CenterPoint point in points)
            {
                // Keep track of our retries
                int retry = 1;

                while (true)
                {
                    // Create a shape
                    IPoly p = Geometry.CreateShape(parent, point.Point,
                        retry * (Constants.SegmentAverageWidth - log));

                    // If we have no shape, this is automatically
                    // included.
                    if (shape == null)
                    {
                        shape = p;
                        break;
                    }

                    // We have another shape, so we want to build up
                    // an intersection to make sure they are touching.
                    if (!shape.HasIntersection(p))
                    {
                        // If there is no intersection, then we need
                        // to try again and make the radius range larger.
                        retry++;
                        continue;
                    }

                    // Make a union of the two shapes
                    IPoly union = shape.Union(p);

                    // See if we have two shapes
                    if (union.InnerPolygonCount > 1)
                    {
                        // We didn't quite reach each other
                        retry++;
                        continue;
                    }

                    // Set the new shape
                    shape = union;
                    break;
                }
            }

            // Remove both junction shapes from this
            //shape = shape.Difference(parent.InternalShape);
            //shape = shape.Difference(child.InternalShape);

            #if DEBUG
            // Show timing information
            stopwatch.Stop();
            Log.Debug("  Shape Time: {0}", stopwatch.Elapsed);
            stopwatch.Reset();
            stopwatch.Start();
            #endif

            // Add the shape to the list
            segment.InternalShape = shape;

            // Set up the center line and optimize it
            segment.CenterPoints.AddAll(points);
            segment.CenterPoints.Optimize();

            #if DEBUG
            // Show timing information
            stopwatch.Stop();
            Log.Debug("Optimze Time: {0}", stopwatch.Elapsed);
            #endif

            // Return the results
            return segment;
        }