Archive Browser
Download SliceRectangleSample.zip, last updated 10/02/2013 (23.18 KB)
Download- md5: 1e8ccdf10305cc43789e4fa28c96006b
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
namespace SliceRectangleSample
{
// Cyotek Slice Rectangle Sample
// Copyright (c) 2013 Cyotek. All Rights Reserved.
// http://cyotek.com
// http://cyotek.com/blog/dividing-up-a-rectangle-based-on-pairs-of-points-using-csharp
// If you use this code in your applications, attribution or donations are welcome.
internal class Settings
{
#region Constructors
public Settings()
{
this.Segments = new List<Segment>();
}
#endregion
#region Properties
public List<Segment> Segments { get; set; }
public Size Size { get; set; }
private IDictionary<Point, SegmentPoint> Points { get; set; }
private HashSet<Rectangle> Rectangles { get; set; }
#endregion
#region Members
public void Calculate()
{
this.CalculatePoints();
this.CalculateRectangles();
}
public SegmentPoint[] GetPoints()
{
return this.Points != null ? this.Points.Values.ToArray() : new SegmentPoint[0];
}
public Rectangle[] GetRectangles()
{
return this.Rectangles != null ? this.Rectangles.ToArray() : new Rectangle[0];
}
public void Load(string fileName)
{
this.Segments = new List<Segment>();
this.Points = null;
using (FileStream stream = File.OpenRead(fileName))
{
using (TextReader reader = new StreamReader(stream))
{
string[] data;
int segmentCount;
data = reader.ReadLine().Split(',');
this.Size = new Size(Convert.ToInt32(data[0]), Convert.ToInt32(data[1]));
segmentCount = Convert.ToInt32(reader.ReadLine());
for (int i = 0; i < segmentCount; i++)
{
Segment segment;
data = reader.ReadLine().Split(',');
segment = new Segment { Location = new Point(Convert.ToInt32(data[0]), Convert.ToInt32(data[1])), Size = Convert.ToInt32(data[2]), Orientation = (SegmentOrientation)Enum.Parse(typeof(SegmentOrientation), data[3], true) };
this.Segments.Add(segment);
}
}
}
this.Calculate();
}
public void Save(string fileName)
{
using (FileStream stream = File.OpenWrite(fileName))
{
using (TextWriter writer = new StreamWriter(stream))
{
writer.WriteLine("{0},{1}", this.Size.Width, this.Size.Height);
writer.WriteLine(this.Segments.Count);
foreach (Segment segment in this.Segments)
writer.WriteLine("{0},{1},{2},{3}", segment.Location.X, segment.Location.Y, segment.Size, segment.Orientation);
}
}
}
private void CalculatePoints()
{
List<Segment> segments;
segments = new List<Segment>();
this.Points = new Dictionary<Point, SegmentPoint>();
// add segments representing the edges
segments.Add(new Segment { Location = Point.Empty, Size = this.Size.Width, Orientation = SegmentOrientation.Horizontal });
segments.Add(new Segment { Location = new Point(0, this.Size.Height), Size = this.Size.Width, Orientation = SegmentOrientation.Horizontal });
segments.Add(new Segment { Location = Point.Empty, Size = this.Size.Height, Orientation = SegmentOrientation.Vertical });
segments.Add(new Segment { Location = new Point(this.Size.Width, 0), Size = this.Size.Height, Orientation = SegmentOrientation.Vertical });
// add the rest of the segments
segments.AddRange(this.Segments);
segments.Sort((a, b) =>
{
int result = a.Location.X.CompareTo(b.Location.X);
if (result == 0)
result = a.Location.Y.CompareTo(b.Location.Y);
return result;
});
foreach (Segment segment in segments)
{
Segment currentSegment;
// add the segment points
this.UpdatePoint(segment.Location, segment.Orientation == SegmentOrientation.Horizontal ? SegmentPointConnections.Left : SegmentPointConnections.Top);
this.UpdatePoint(segment.EndLocation, segment.Orientation == SegmentOrientation.Horizontal ? SegmentPointConnections.Right : SegmentPointConnections.Bottom);
// calculate any intersecting points
currentSegment = segment;
foreach (Segment otherSegment in segments.Where(s => s != currentSegment))
{
Point intersection;
intersection = Intersection.FindLineIntersection(segment.Location, segment.EndLocation, otherSegment.Location, otherSegment.EndLocation);
if (!intersection.IsEmpty)
{
SegmentPointConnections flags;
flags = SegmentPointConnections.None;
if (intersection != segment.Location && intersection != segment.EndLocation)
{
if (segment.Orientation == SegmentOrientation.Horizontal)
flags |= (SegmentPointConnections.Left | SegmentPointConnections.Right);
else
flags |= (SegmentPointConnections.Top | SegmentPointConnections.Bottom);
}
else if (intersection != otherSegment.Location && intersection != otherSegment.EndLocation)
{
if (otherSegment.Orientation == SegmentOrientation.Horizontal)
flags |= (SegmentPointConnections.Left | SegmentPointConnections.Right);
else
flags |= (SegmentPointConnections.Top | SegmentPointConnections.Bottom);
}
if (flags != SegmentPointConnections.None)
this.UpdatePoint(intersection, flags);
}
}
}
}
private void CalculateRectangles()
{
SegmentPoint[] horizontalPoints;
SegmentPoint[] verticalPoints;
this.Rectangles = new HashSet<Rectangle>();
horizontalPoints = this.Points.Values.OrderBy(p => p.X).ToArray();
verticalPoints = this.Points.Values.OrderBy(p => p.Y).ToArray();
foreach (SegmentPoint topLeft in this.Points.Values.Where(p => p.Connections.HasFlag(SegmentPointConnections.Left | SegmentPointConnections.Top)))
{
SegmentPoint topRight;
SegmentPoint bottomLeft;
topRight = horizontalPoints.FirstOrDefault(p => p.X > topLeft.X && p.Y == topLeft.Y && p.Connections.HasFlag(SegmentPointConnections.Right | SegmentPointConnections.Top));
bottomLeft = verticalPoints.FirstOrDefault(p => p.X == topLeft.X && p.Y > topLeft.Y && p.Connections.HasFlag(SegmentPointConnections.Left | SegmentPointConnections.Bottom));
if (topRight != null && bottomLeft != null)
{
SegmentPoint bottomRight;
bottomRight = horizontalPoints.FirstOrDefault(p => p.X == topRight.X && p.Y == bottomLeft.Y && p.Connections.HasFlag(SegmentPointConnections.Right | SegmentPointConnections.Bottom));
if (bottomRight != null)
{
Rectangle rectangle;
rectangle = new Rectangle(topLeft.X, topLeft.Y, bottomRight.X - topLeft.X, bottomRight.Y - topLeft.Y);
this.Rectangles.Add(rectangle);
}
}
}
}
private void UpdatePoint(Point location, SegmentPointConnections connections)
{
SegmentPoint point;
if (!this.Points.TryGetValue(location, out point))
{
point = new SegmentPoint { Location = location, Connections = connections };
this.Points.Add(point.Location, point);
}
else if (!point.Connections.HasFlag(connections))
point.Connections |= connections;
}
#endregion
}
}
Donate
This software may be used free of charge, but as with all free software there are costs involved to develop and maintain.
If this site or its services have saved you time, please consider a donation to help with running costs and timely updates.
Donate