public void AddSegment(FloorSegment segment)
            {
                _segments.Add(segment);
                int size = segment.points.Length;

                for (int p = 0; p < size; p++)
                {
                    _bounds.Encapsulate(segment.points[p].vx, segment.points[p].vy);
                }
            }
 public void AddSegment(FloorSegment segment)
 {
     capturedSegments.Add(segment);
     processSegments.Add(segment);
     if (segment.area < 0)
     {
         Debug.Log("AddSegment minus area");
     }
     currentArea += segment.area;
 }
            public float BestFit(FloorSegment target)
            {
                if (target == this)
                {
                    return(-1);
                }
                int   targetSize = target.points.Length;
                int   pointSize  = points.Length;
                float output     = 0;//default is there is no fit

                for (int p = 0; p < pointSize; p++)
                {
                    Vector2Int point = points[p];
                    for (int t = 0; t < targetSize; t++)
                    {
                        Vector2Int targetPoint = target.points[t];
                        float      sqrMag      = (targetPoint - point).SqrMagnitudeFloat();
                        if (sqrMag < 0.1f)
                        {
                            output += 0.5f;
                        }
                        else  //test for two lines joined
                        {
                            Vector2Int pointB = points[p < pointSize - 1 ? p + 1 : 0];
                            if (Colinear(point, pointB, targetPoint))
                            {
                                Vector2Int targetPointB = target.points[t < targetSize - 1 ? t + 1 : 0];
                                if (Colinear(point, pointB, targetPointB))
                                {
                                    output += 1f;
                                }
                            }
                        }
                    }
                }

                return(Mathf.Clamp01(output));
            }
 // Use this for initialization
 void Start()
 {
     FloorSegment = this.GetComponentInParent<FloorSegment>();
 }
        public void Execute()
        {
            calculatedPartitions.Clear();


            //remvoe duplicate points
            for (int i = 0; i < shape.Count; i++)
            {
                Vector2Int p0   = shape[i];
                Vector2Int p1   = shape[i < shape.Count - 1 ? i + 1 : 0];
                float      sqrM = Vector2Int.SqrMagnitudeFloat(p1, p0);
                if (sqrM < Mathf.Epsilon)
                {
                    shape.RemoveAt(i);
                    i--;
                }
            }

            //break poly down into convex shapes
            TPPLPoly poly = new TPPLPoly();

            for (int i = 0; i < shape.Count; i++)
            {
                poly.Points.Add(new TPPLPoint(shape[i].x, shape[i].y));
            }

            if (BuildrPolyClockwise.Check(shape))
            {
                poly.SetOrientation(TPPLOrder.CW);
            }
            else
            {
                poly.SetOrientation(TPPLOrder.CCW);
            }

            List <TPPLPoly> parts         = new List <TPPLPoly>();
            TPPLPartition   tpplPartition = new TPPLPartition();

            tpplPartition.ConvexPartition_HM(poly, parts);

            //generate an irregular grid upon each convex poly
            int          partCount    = parts.Count;
            PlotSplitter plotSplitter = new PlotSplitter();

            floorSegments.Clear();
            for (int p = 0; p < partCount; p++)
            {
                TPPLPoly          partPoly   = parts[p];
                int               partSize   = partPoly.Count;
                List <Vector2Int> plotPoints = new List <Vector2Int>();
                for (int w = 0; w < partSize; w++)
                {
                    TPPLPoint  tpplPoint = partPoly[w];
                    Vector2Int p0        = new Vector2Int(tpplPoint.X, tpplPoint.Y);
                    plotPoints.Add(p0);
                }

                Plot plot = new Plot(seed, plotPoints, minimumWallUnitSpacing);
                plot.splitSettings = splitSettings;
                plotSplitter.Execute(plot, seed);
                int splitCount = plotSplitter.plots.Count;
                for (int s = 0; s < splitCount; s++)
                {
                    IPlot        segmentPlot = plotSplitter.plots[s];
                    Vector2Int[] points      = Vector2Int.Parse(segmentPlot.pointsV2);
                    FloorSegment segment     = new FloorSegment(segmentPlot.area, segmentPlot.flatbounds, points);
                    floorSegments.Add(segment);
                }
            }

            int segmentCount = floorSegments.Count;
            List <FloorSegment> availableSegments = new List <FloorSegment>(floorSegments);
            int       restrictedAreaCount         = restrictedAreas.Count;
            Partition restrictedPartition         = null;

            for (int r = 0; r < restrictedAreaCount; r++)
            {
                RestrictedArea area       = restrictedAreas[r];
                FlatBounds     areaBounds = new FlatBounds();
                areaBounds.Encapsulate(Vector2Int.Parse(area.shape));
                for (int fs = 0; fs < segmentCount; fs++)
                {
                    FloorSegment segment = availableSegments[fs];
                    if (areaBounds.Overlaps(segment.bounds))
                    {
                        if (JMath.ShapesIntersect(Vector2Int.Parse(area.shape), Vector2Int.Parse(segment.points)))
                        {
                            if (restrictedPartition == null)
                            {
                                restrictedPartition = new Partition();
                            }
                            restrictedPartition.AddSegment(segment);
                            availableSegments.Remove(segment);
                            segmentCount--;
                            fs--;
                        }
                    }
                }
            }

            //Link up floor segments
            segmentCount = availableSegments.Count;
            for (int x = 0; x < segmentCount; x++)
            {
                FloorSegment subject       = floorSegments[x];
                FlatBounds   subjectBounds = subject.nBounds;
                for (int y = 0; y < segmentCount; y++)
                {
                    if (x == y)
                    {
                        continue;
                    }

                    FloorSegment candidate = floorSegments[y];


                    FlatBounds candidateBounds = candidate.nBounds;
                    if (subjectBounds.Overlaps(candidateBounds))
                    {
                        if (candidate.neighbours.Contains(subject))
                        {
                            continue;
                        }
                        subject.neighbours.Add(candidate);
                        candidate.neighbours.Add(subject);
                    }
                }
            }

            //Grow out partitions to fill the available space
            List <PartitionGrowth> partitionGs = new List <PartitionGrowth>();
            Dictionary <FloorSegment, FloorSegmentClaim> segmentClaims = new Dictionary <FloorSegment, FloorSegmentClaim>();

            for (int i = 0; i < partitions.Count; i++)
            {
                partitionGs.Add(new PartitionGrowth(partitions[i]));
            }

            int it = 1000;

            while (true)
            {
                int   growthCount = partitionGs.Count;
                int   completePartitionGrowths = 0;
                int[] partitionGrowthAmount    = new int[growthCount];
                segmentClaims.Clear();

                for (int g = 0; g < growthCount; g++)
                {
                    PartitionGrowth partitionG = partitionGs[g];
                    if (!partitionG.active)
                    {
                        completePartitionGrowths++;
                        continue;
                    }

                    if (availableSegments.Count == 0)
                    {
                        break;
                    }

                    //assign inital segment to begin partition from
                    if (!partitionG.initialised)
                    {
                        float        nearestSqrMag = float.PositiveInfinity;
                        FloorSegment candidate     = availableSegments[0];
                        for (int x = 0; x < availableSegments.Count; x++)
                        {
                            FloorSegment subject = availableSegments[x];
                            float        sqrMag  = Vector2Int.SqrMagnitudeFloat(partitionG.subject.position, subject.position);
                            if (sqrMag < nearestSqrMag)
                            {
                                candidate     = subject;
                                nearestSqrMag = sqrMag;
                            }
                        }

                        partitionG.capturedSegments.Add(candidate);
                        partitionG.processSegments.Add(candidate);
                        availableSegments.Remove(candidate);
                        partitionG.initialised   = true;
                        partitionGrowthAmount[g] = 1;
                        continue;//don't start growth until next iteration
                    }

                    //grow partition
                    if (partitionG.initialised)
                    {
                        List <FloorSegment> neighbourCandiates = new List <FloorSegment>();
                        int processCount = partitionG.processSegments.Count;
//                        float additionalArea = 0;
                        for (int p = 0; p < processCount; p++)
                        {
                            FloorSegment processSegment        = partitionG.processSegments[p];
                            int          processNeighbourCount = processSegment.neighbours.Count;
                            for (int n = 0; n < processNeighbourCount; n++)
                            {
                                FloorSegment neighbour             = processSegment.neighbours[n];
                                bool         isAvailable           = availableSegments.Contains(neighbour);
                                bool         notDuplicateNeighbour = !neighbourCandiates.Contains(neighbour);
                                if (isAvailable && notDuplicateNeighbour)
                                {
                                    neighbourCandiates.Add(neighbour);
                                    float fit = processSegment.BestFit(neighbour);
                                    if (fit > Mathf.Epsilon)
                                    {
                                        FloorSegmentClaim newClaim = new FloorSegmentClaim();
                                        newClaim.partition   = partitionG;
                                        newClaim.growthIndex = g;
                                        newClaim.segment     = neighbour;
                                        newClaim.priority    = partitionG.subject.priority * fit;

                                        if (!segmentClaims.ContainsKey(neighbour))
                                        {
                                            segmentClaims.Add(neighbour, newClaim);
                                        }
                                        else
                                        {
                                            FloorSegmentClaim currentClaim = segmentClaims[neighbour];
                                            if (currentClaim.priority < newClaim.priority)
                                            {
                                                segmentClaims[neighbour] = newClaim;
                                            }
                                        }
                                    }
//                                    additionalArea += neighbour.area;
                                }
                            }
                        }

//                        int neighbourCandiatesCount = neighbourCandiates.Count;
//                        for (int n = 0; n < neighbourCandiatesCount; n++) {
//                            FloorSegment segement = neighbourCandiates[n];
//
//                            if (segmentClaims.ContainsKey(segement)) {
//
//                            }
//                            else {
//
//                            }
//                        }
                        //                        if (neighbourCandiatesCount > 0) {
                        //
                        //                            bool canAddAll = partitionG.AvailableArea(additionalArea);
                        //                            if (canAddAll) {
                        //                                partitionG.processSegments.Clear();
                        //                                for (int n = 0; n < neighbourCandiatesCount; n++)
                        //                                    availableSegments.Remove(neighbourCandiates[n]);
                        ////                                partitionG.AddSegments(neighbourCandiates);
                        //                            }
                        //                            else {
                        //                                //                                TODO partial add (?)
                        ////                                partitionG.AddSegments(neighbourCandiates);
                        //                                partitionG.Complete();
                        //                            }
                        //                        }
                        //                        else {
                        //                            partitionG.Complete();
                        //                        }

//                        if (partitionG.processSegments.Count == 0)
//                            partitionG.Complete();
                    }
                }

                foreach (KeyValuePair <FloorSegment, FloorSegmentClaim> kv in segmentClaims)
                {
                    //TODO - support instance when new areas to add are too large
                    //TODO - fall back on partial adding of single side
                    FloorSegmentClaim claim = kv.Value;
                    claim.partition.AddSegment(claim.segment);
                    availableSegments.Remove(claim.segment);
                    partitionGrowthAmount[claim.growthIndex]++;
                }

                for (int g = 0; g < growthCount; g++)
                {
                    PartitionGrowth partitionG = partitionGs[g];
                    if (!partitionG.active)
                    {
                        continue;
                    }
//                    Debug.Log(g+" "+ partitionG.AcceptableAreaUsed()+" " + partitionGrowthAmount[g]+" "+ partitionG.processSegments.Count);
                    if (partitionG.AcceptableAreaUsed() || partitionGrowthAmount[g] == 0 || partitionG.processSegments.Count == 0)
                    {
                        completePartitionGrowths++;
                        partitionG.Complete();
                    }
                }

                if (completePartitionGrowths == growthCount) //all partitions have been completed
                {
                    break;
                }

                if (availableSegments.Count == 0)
                {
                    foreach (PartitionGrowth part in partitionGs)
                    {
                        if (part.active)
                        {
                            part.Complete();
                        }
                    }

                    foreach (PartitionGrowth part in partitionGs)
                    {
                        int childCount = part.subject.children.Count;
                        if (childCount > 0)
                        {
                            for (int c = 0; c < childCount; c++)
                            {
                                partitionGs.Add(new PartitionGrowth(part.subject.children[c]));
                            }
                            part.subject.children.Clear();
                            availableSegments.AddRange(part.capturedSegments);
                            part.capturedSegments.Clear();
                            break;
                        }
                    }

                    if (availableSegments.Count == 0)
                    {
                        break;
                    }
                }

                it--;
                if (it == 0)
                {
                    Debug.Log(" MAX reached!");
                    Debug.Log(availableSegments.Count);
                    foreach (PartitionGrowth pg in partitionGs)
                    {
                        Debug.Log(pg.processSegments.Count);
                        Debug.Log(pg.capturedSegments.Count);
                        pg.Complete();
                    }
                    break;
                }
            }


            foreach (PartitionGrowth part in partitionGs)
            {
                if (part.active)
                {
                    part.Complete();
                }
                calculatedPartitions.Add(part.subject);
            }

//            if (floorplan != null)
//            {
//                int roomCount = calculatedPartitions.Count;
//
//
//
//
//                Room floorplanRoom = new Room();
//
//
//                floorplan.rooms.Add();
//            }

            //            foreach (Partition part in partitions) {
            //                Debug.Log(part.segments.Count);
            //            }
        }
示例#6
0
        private void DrawData(int tileSize)
        {
            // Draw the floorplan
            MainCanvas.Children.Clear();
            for (int top = 0; top < fpHeight; top++)
            {
                for (int left = 0; left < fpWidth; left++)
                {
                    if (fp.floorGrid[top, left] != null)
                    {
                        FloorSegment thisSegment = fp.floorGrid[top, left];
                        if (!colorDict.ContainsKey(thisSegment.GroupID))
                        {
                            colorDict.Add(thisSegment.GroupID, PickBrush());
                        }
                        Rectangle newRect = new Rectangle()
                        {
                            Width  = tileSize,
                            Height = tileSize,
                            Fill   = colorDict[thisSegment.GroupID]
                        };
                        RenderOptions.SetEdgeMode(newRect, EdgeMode.Aliased);

                        // Draw the lines between squares if they belong to different rooms
                        FloorSegment northSegment  = fp.IsInBounds(top - 1, left) ? fp.floorGrid[top - 1, left] : null;
                        bool         drawNorthLine = northSegment == null ? true : (northSegment.RoomID != thisSegment.RoomID) ? true : false;
                        if (drawNorthLine)
                        {
                            Line newLine = new Line()
                            {
                                Stroke          = Brushes.Black,
                                StrokeThickness = 2,
                                X1 = left * tileSize,
                                Y1 = top * tileSize,
                                X2 = (left * tileSize) + tileSize,
                                Y2 = top * tileSize
                            };
                            MainCanvas.Children.Add(newLine);
                        }

                        FloorSegment westSegment  = fp.IsInBounds(top, left - 1) ? fp.floorGrid[top, left - 1] : null;
                        bool         drawWestLine = westSegment == null ? true : (westSegment.RoomID != thisSegment.RoomID) ? true : false;
                        if (drawWestLine)
                        {
                            Line newLine = new Line()
                            {
                                Stroke          = Brushes.Black,
                                StrokeThickness = 2,
                                X1 = left * tileSize,
                                Y1 = top * tileSize,
                                X2 = left * tileSize,
                                Y2 = (top * tileSize) + tileSize
                            };
                            MainCanvas.Children.Add(newLine);
                        }

                        FloorSegment eastSegment  = fp.IsInBounds(top, left + 1) ? fp.floorGrid[top, left + 1] : null;
                        bool         drawEastLine = eastSegment == null ? true : (eastSegment.RoomID != thisSegment.RoomID) ? true : false;
                        if (drawEastLine)
                        {
                            Line newLine = new Line()
                            {
                                Stroke          = Brushes.Black,
                                StrokeThickness = 2,
                                X1 = (left * tileSize) + tileSize,
                                Y1 = top * tileSize,
                                X2 = (left * tileSize) + tileSize,
                                Y2 = (top * tileSize) + tileSize
                            };
                            MainCanvas.Children.Add(newLine);
                        }

                        FloorSegment southSegment  = fp.IsInBounds(top + 1, left) ? fp.floorGrid[top + 1, left] : null;
                        bool         drawSouthLine = southSegment == null ? true : (southSegment.RoomID != thisSegment.RoomID) ? true : false;
                        if (drawSouthLine)
                        {
                            Line newLine = new Line()
                            {
                                Stroke          = Brushes.Black,
                                StrokeThickness = 2,
                                X1 = left * tileSize,
                                Y1 = (top * tileSize) + tileSize,
                                X2 = (left * tileSize) + tileSize,
                                Y2 = (top * tileSize) + tileSize
                            };
                            MainCanvas.Children.Add(newLine);
                        }
                        MainCanvas.Children.Add(newRect);
                        Canvas.SetLeft(newRect, left * tileSize);
                        Canvas.SetTop(newRect, top * tileSize);

                        if (drawRoomNumbers)
                        {
                            TextBlock tbRoomNum = new TextBlock();
                            tbRoomNum.Inlines.Add(new Run(fp.floorGrid[top, left].RoomID.ToString()));
                            RenderOptions.SetEdgeMode(tbRoomNum, EdgeMode.Aliased);
                            MainCanvas.Children.Add(tbRoomNum);
                            Canvas.SetLeft(tbRoomNum, left * tileSize + 6);
                            Canvas.SetTop(tbRoomNum, top * tileSize + 6);
                        }
                        else if (drawGroupNumbers)
                        {
                            TextBlock tbGroupNum = new TextBlock();
                            tbGroupNum.Inlines.Add(new Run(fp.floorGrid[top, left].GroupID.ToString()));
                            RenderOptions.SetEdgeMode(tbGroupNum, EdgeMode.Aliased);
                            MainCanvas.Children.Add(tbGroupNum);
                            Canvas.SetLeft(tbGroupNum, left * tileSize + 6);
                            Canvas.SetTop(tbGroupNum, top * tileSize + 6);
                        }
                        else if (drawCorridorGroups)
                        {
                            TextBlock        tbGroupNum  = new TextBlock();
                            HashSet <string> groupValues = fp.floorGrid[top, left].ConnectedCorridorIDs;
                            if (groupValues.Count > 0)
                            {
                                string groupCSV = String.Join(",", groupValues.Select(x => x.ToString()).ToArray());
                                tbGroupNum.Inlines.Add(new Run(groupCSV));
                                RenderOptions.SetEdgeMode(tbGroupNum, EdgeMode.Aliased);
                                MainCanvas.Children.Add(tbGroupNum);
                                Canvas.SetLeft(tbGroupNum, left * tileSize + 6);
                                Canvas.SetTop(tbGroupNum, top * tileSize + 6);
                            }
                        }
                    }
                }
            }

            // Draw the remaining eligible segments
            if (fp.pause)
            {
                foreach (DirectionalSegment ds in fp.eligibleFloorSegments)
                {
                    Rectangle newRect = new Rectangle()
                    {
                        Width           = tileSize,
                        Height          = tileSize,
                        Stroke          = Brushes.Black,
                        StrokeThickness = 1
                    };
                    MainCanvas.Children.Add(newRect);
                    Canvas.SetLeft(newRect, ds.Left * tileSize);
                    Canvas.SetTop(newRect, ds.Top * tileSize);
                }
            }
            // Signal the algorithm to continue
            fp.waitEvent.Set();
            labelCountRoom.Content = fp.currRoomID.ToString();
        }
示例#7
0
        private void DrawHallways(int tileSize, int hallwaySize)
        {
            // Create a path for drawing the hallways
            Path hallwayPath = new Path();

            hallwayPath.Stroke          = Brushes.Black;
            hallwayPath.StrokeThickness = 1;
            SolidColorBrush mySolidColorBrush = new SolidColorBrush();

            mySolidColorBrush.Color = Colors.White;
            hallwayPath.Fill        = mySolidColorBrush;

            // Use a composite geometry for adding the hallways to
            CombinedGeometry hallwayGeometryGroup = new CombinedGeometry();

            hallwayGeometryGroup.GeometryCombineMode = GeometryCombineMode.Union;
            hallwayGeometryGroup.Geometry1           = null;
            hallwayGeometryGroup.Geometry2           = null;

            for (int top = 0; top < fpHeight; top++)
            {
                for (int left = 0; left < fpWidth; left++)
                {
                    if (fp.floorGrid[top, left] != null)
                    {
                        FloorSegment thisSegment = fp.floorGrid[top, left];

                        // If the segment above is in bounds and from a different group, we draw a hallway.
                        // Otherwise, if it's a different room of the same group, we draw a wall.

                        FloorSegment northSegment = fp.IsInBounds(top - 1, left) ? fp.floorGrid[top - 1, left] : null;
                        if (northSegment != null)
                        {
                            if (northSegment.GroupID != thisSegment.GroupID)
                            {
                                RectangleGeometry newHallwayGeometry = new RectangleGeometry(
                                    new Rect(
                                        (left * tileSize) - (hallwaySize / 2),
                                        (top * tileSize) - (hallwaySize / 2),
                                        tileSize + hallwaySize,
                                        hallwaySize));
                                hallwayGeometryGroup = new CombinedGeometry()
                                {
                                    Geometry1 = hallwayGeometryGroup,
                                    Geometry2 = newHallwayGeometry
                                };
                            }
                        }

                        FloorSegment southSegment = fp.IsInBounds(top + 1, left) ? fp.floorGrid[top + 1, left] : null;
                        if (southSegment != null)
                        {
                            if (southSegment.GroupID != thisSegment.GroupID)
                            {
                                RectangleGeometry newHallwayGeometry = new RectangleGeometry(
                                    new Rect(
                                        (left * tileSize) - (hallwaySize / 2),
                                        ((top * tileSize) + tileSize) - (hallwaySize / 2),
                                        tileSize + hallwaySize,
                                        hallwaySize));
                                hallwayGeometryGroup = new CombinedGeometry()
                                {
                                    Geometry1 = hallwayGeometryGroup,
                                    Geometry2 = newHallwayGeometry
                                };
                            }
                        }

                        FloorSegment eastSegment = fp.IsInBounds(top, left + 1) ? fp.floorGrid[top, left + 1] : null;
                        if (eastSegment != null)
                        {
                            if (eastSegment.GroupID != thisSegment.GroupID)
                            {
                                RectangleGeometry newHallwayGeometry = new RectangleGeometry(
                                    new Rect(
                                        ((left * tileSize) + tileSize) - (hallwaySize / 2),
                                        (top * tileSize) - (hallwaySize / 2),
                                        hallwaySize,
                                        tileSize + hallwaySize));
                                hallwayGeometryGroup = new CombinedGeometry()
                                {
                                    Geometry1 = hallwayGeometryGroup,
                                    Geometry2 = newHallwayGeometry
                                };
                            }
                        }

                        FloorSegment westSegment = fp.IsInBounds(top, left - 1) ? fp.floorGrid[top, left - 1] : null;
                        if (westSegment != null)
                        {
                            if (westSegment.GroupID != thisSegment.GroupID)
                            {
                                RectangleGeometry newHallwayGeometry = new RectangleGeometry(
                                    new Rect(
                                        (left * tileSize) - (hallwaySize / 2),
                                        (top * tileSize) - (hallwaySize / 2),
                                        hallwaySize,
                                        tileSize + hallwaySize));
                                hallwayGeometryGroup = new CombinedGeometry()
                                {
                                    Geometry1 = hallwayGeometryGroup,
                                    Geometry2 = newHallwayGeometry
                                };
                            }
                        }
                    }
                }
            }
            hallwayPath.Data = hallwayGeometryGroup;
            RenderOptions.SetEdgeMode(hallwayPath, EdgeMode.Aliased);
            MainCanvas.Children.Add(hallwayPath);

            // Draw the remaining eligible segments
            if (fp.pause)
            {
                foreach (DirectionalSegment ds in fp.eligibleFloorSegments)
                {
                    Rectangle newRect = new Rectangle()
                    {
                        Width           = tileSize,
                        Height          = tileSize,
                        Stroke          = Brushes.Black,
                        StrokeThickness = 1
                    };
                    MainCanvas.Children.Add(newRect);
                    Canvas.SetLeft(newRect, ds.Left * tileSize);
                    Canvas.SetTop(newRect, ds.Top * tileSize);
                }
            }
            // Signal the algorithm to continue
            fp.waitEvent.Set();
            labelCountRoom.Content = fp.currRoomID.ToString();
        }
示例#8
0
        private void DrawDoors(int tileSize, int hallwaySize)
        {
            // Create a path for drawing the hallways
            Path doorsPath = new Path();

            doorsPath.Stroke          = Brushes.Black;
            doorsPath.StrokeThickness = 1;
            SolidColorBrush mySolidColorBrush = new SolidColorBrush();

            mySolidColorBrush.Color = Colors.Black;
            doorsPath.Fill          = mySolidColorBrush;

            // Use a composite geometry for adding the doors to
            CombinedGeometry doorsGeometryGroup = new CombinedGeometry();

            doorsGeometryGroup.GeometryCombineMode = GeometryCombineMode.Union;
            doorsGeometryGroup.Geometry1           = null;
            doorsGeometryGroup.Geometry2           = null;

            for (int top = 0; top < fpHeight; top++)
            {
                for (int left = 0; left < fpWidth; left++)
                {
                    if (fp.floorGrid[top, left] != null)
                    {
                        FloorSegment thisSegment = fp.floorGrid[top, left];
                        double       doorX       = 0;
                        double       doorY       = 0;
                        double       doorWidth   = 0;
                        double       doorHeight  = 0;
                        // position the doors differently depending on weather or not there's a hallway.  Math, bitches.
                        foreach (enumDirection nextDoorDir in thisSegment.Doors)
                        {
                            switch (nextDoorDir)
                            {
                            case enumDirection.North:
                                FloorSegment northSegment = fp.IsInBounds(top - 1, left) ? fp.floorGrid[top - 1, left] : null;
                                doorX      = (left * tileSize) + (tileSize / 2) - (hallwaySize / 2);
                                doorY      = northSegment != null ? northSegment.GroupID != thisSegment.GroupID ? (top * tileSize) + (hallwaySize / 4) : (top * tileSize) - (hallwaySize / 4) : (top * tileSize) - (hallwaySize / 4);
                                doorWidth  = hallwaySize;
                                doorHeight = hallwaySize / 2;
                                break;

                            case enumDirection.South:
                                FloorSegment southSegment = fp.IsInBounds(top + 1, left) ? fp.floorGrid[top + 1, left] : null;
                                doorX      = (left * tileSize) + (tileSize / 2) - (hallwaySize / 2);
                                doorY      = southSegment != null ? southSegment.GroupID != thisSegment.GroupID ? ((top * tileSize) + tileSize) - ((hallwaySize / 4) * 3) : ((top * tileSize) + tileSize) - (hallwaySize / 4) : ((top * tileSize) + tileSize) - (hallwaySize / 4);
                                doorWidth  = hallwaySize;
                                doorHeight = hallwaySize / 2;
                                break;

                            case enumDirection.East:
                                FloorSegment eastSegment = fp.IsInBounds(top, left + 1) ? fp.floorGrid[top, left + 1] : null;
                                doorX      = eastSegment != null ? eastSegment.GroupID != thisSegment.GroupID ? ((left * tileSize) + tileSize) - ((hallwaySize / 4) * 3) : ((left * tileSize) + tileSize) - (hallwaySize / 4) : ((left * tileSize) + tileSize) - (hallwaySize / 4);
                                doorY      = (top * tileSize) + (tileSize / 2) - (hallwaySize / 2);
                                doorWidth  = hallwaySize / 2;
                                doorHeight = hallwaySize;
                                break;

                            case enumDirection.West:
                                FloorSegment westSegment = fp.IsInBounds(top, left - 1) ? fp.floorGrid[top, left - 1] : null;
                                doorX      = westSegment != null ? westSegment.GroupID != thisSegment.GroupID ? (left * tileSize) + (hallwaySize / 4) : (left * tileSize) - (hallwaySize / 4) : (left * tileSize) - (hallwaySize / 4);
                                doorY      = (top * tileSize) + (tileSize / 2) - (hallwaySize / 2);
                                doorWidth  = hallwaySize / 2;
                                doorHeight = hallwaySize;
                                break;
                            }
                            RectangleGeometry newDoorGeometry = new RectangleGeometry(new Rect(doorX, doorY, doorWidth, doorHeight));
                            doorsGeometryGroup = new CombinedGeometry()
                            {
                                Geometry1 = doorsGeometryGroup,
                                Geometry2 = newDoorGeometry
                            };
                        }
                    }
                }
            }

            doorsPath.Data = doorsGeometryGroup;
            RenderOptions.SetEdgeMode(doorsPath, EdgeMode.Aliased);
            MainCanvas.Children.Add(doorsPath);
        }