/// <summary> /// Populates a junction with clutter, bonuses, and other /// stuff. /// </summary> public void Create(Segment segment) { // Basically create a random number of modules and place // them in the stage. MersenneRandom random = segment.ParentJunction.Random; Junction junction = segment.ChildJunction; int moduleCount = junction.Random.Next(0, 40); for (int i = 0; i < moduleCount; i++) { // Find a random vertex and basically center it // somewhere along the line between the center and the // vertex. int pointCount = junction.InternalShape.PointCount; int pointIndex = random.Next(0, pointCount); float x = (float) junction.InternalShape.GetX(pointIndex); float y = (float) junction.InternalShape.GetY(pointIndex); // We get a place in the middle, but not too // close. Since the junction center is always at (0, // 0), this simplifies finding the point. float weight = random.NextSingle(0.1f, 0.9f); float cx = x * weight; float cy = y * weight; // Create the mobile Create(segment, random, cx, cy); } }
/// <summary> /// Creates a random mobile object at the given location. /// </summary> private void Create( Segment segment, MersenneRandom random, float x, float y) { // Figure out the type Mobile m = new HousingBubble(); int pick = random.Next(10); if (pick == 0) m = new ContainmentModule(); else if (pick < 5) m = new EngineModule(); // Create a housing bubble PointF p = segment.ChildJunctionPoint; m.Point = new PointF(p.X + x, p.Y + y); m.Radius = random.NextSingle(5, 20); // Add it segment.ParentJunction.Mobiles.Add(m); }
/// <summary> /// Creates a new segment with the ends swapped and the /// polygons reversed. /// </summary> public Segment Swap() { // Create a new segment Segment s = new Segment(); s.child = parent; s.parent = child; s.ChildJunctionPoint = new PointF( -ChildJunctionPoint.X, -ChildJunctionPoint.Y); // Reverse the relative coordinates of the segment double dx = -ChildJunctionPoint.X; double dy = -ChildJunctionPoint.Y; // Shift the polygon over as appropriate s.internalShape = internalShape.Translate(dx, dy); // Reverse the center lines foreach (CenterPoint cp in centerPoints) { s.centerPoints.Add( new CenterPoint((float) dx + cp.X, (float) dy + cp.Y)); } // Return the results return s; }
/// <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; }
/// <summary> /// Returns true if the segment overlaps with the current list. /// </summary> private bool CheckOverlapIntersection( IList<IPoly> overlaps, Segment segment) { // First build up the overlap test shape IPoly newShape = segment.ChildJunction.InternalShape .Translate( segment.ChildJunctionPoint.X, segment.ChildJunctionPoint.Y) .Union(segment.InternalShape); // Now check for an intersection with all the overlaps foreach (IPoly overlap in overlaps) { // If we intersect, then there is an overlap if (overlap.HasIntersection(newShape)) return true; } // Store the circle that represents this junction to // prevent anything from getting too close. IPoly circleTest = Geometry.CreateCircle( segment.ChildJunctionPoint, Constants.OverlapConnectionDistance); //IPoly toRemove = newShape.Intersection(circleTest); overlaps.Add(circleTest); //newShape.Xor(toRemove)); // No intersections, so return false return false; }
/// <summary> /// Renders out the segment between two junctions. /// </summary> private void RenderSegment(Context g, Segment segment) { // Get the shape we need to draw and draw it IPoly poly = segment.InternalShape; if (poly != null) { // Go through the points and draw with a fill RenderPolygon(g, poly, PointF.Empty, new Color(0, 0, 0.5f)); double color = 1; for (int i = 1; i < poly.InnerPolygonCount; i++) { RenderPolygon(g, poly.GetInnerPoly(i), PointF.Empty, new Color(color, 0, 0.5f)); color /= 1.5; } } // Draw the center points foreach (CenterPoint point in segment.CenterPoints) RenderSegmentHandle(g, point); }