1
Polylines / Re: Offset curve toward centroid
« on: March 20, 2013, 07:11:04 PM »
According to Tony Tanzillo's advices at TheSwamp, here's a safer way because of the using of DisposableSet class to insure the newly created polylines to be diposed in case an exception is thrown.
Code: [Select]
using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.AutoCAD.DatabaseServices;
// With the help of Tony Tanzillo's advices
// http://www.theswamp.org/index.php?topic=31862.msg494503#msg494503
namespace OffsetPolylineSample
{
/// <summary>
/// Provides the Offset() extension method for the Polyline type
/// </summary>
public static class PolylineExtension
{
/// <summary>
/// Enumeration of offset side options
/// </summary>
public enum OffsetSide
{
In, Out, Left, Right, Both
}
/// <summary>
/// Offset the source polyline to specified side(s).
/// </summary>
/// <param name="source">The polyline to be offseted.</param>
/// <param name="offsetDist">The offset distance.</param>
/// <param name="side">The offset side(s).</param>
/// <returns>A polyline sequence resulting from the offset of the source polyline.</returns>
public static IEnumerable<Polyline> Offset(this Polyline source, double offsetDist, OffsetSide side)
{
offsetDist = Math.Abs(offsetDist);
using (var plines = new DisposableSet<Polyline>())
{
IEnumerable<Polyline> offsetRight = source.GetOffsetCurves(offsetDist).Cast<Polyline>();
plines.UnionWith(offsetRight);
IEnumerable<Polyline> offsetLeft = source.GetOffsetCurves(-offsetDist).Cast<Polyline>();
plines.UnionWith(offsetLeft);
double areaRight = offsetRight.Select(pline => pline.Area).Sum();
double areaLeft = offsetLeft.Select(pline => pline.Area).Sum();
switch (side)
{
case OffsetSide.In:
return plines.RemoveRange(
areaRight < areaLeft ? offsetRight : offsetLeft);
case OffsetSide.Out:
return plines.RemoveRange(
areaRight < areaLeft ? offsetLeft : offsetRight);
case OffsetSide.Left:
return plines.RemoveRange(offsetLeft);
case OffsetSide.Right:
return plines.RemoveRange(offsetRight);
case OffsetSide.Both:
plines.Clear();
return offsetRight.Concat(offsetLeft);
default:
return null;
}
}
}
}
/// <summary>
/// Represents a set of disposable values.
/// </summary>
/// <typeparam name="T"></typeparam>
public class DisposableSet<T> : HashSet<T>, IDisposable
where T : IDisposable
{
/// <summary>
/// Disposes all items of the current DisposableSet object.
/// </summary>
public void Dispose()
{
if (base.Count > 0)
{
System.Exception last = null;
foreach (T item in this)
{
if (item != null)
{
try
{
item.Dispose();
}
catch (System.Exception ex)
{
last = last ?? ex;
}
}
}
this.Clear();
if (last != null)
throw last;
}
}
/// <summary>
/// Removes all elements in the specified collection from the current DisposableSet object.
/// </summary>
/// <param name="items">The collection of items to remove from the current DisposableSet object.</param>
/// <returns>The collection of items to remove.</returns>
public IEnumerable<T> RemoveRange(IEnumerable<T> items)
{
base.ExceptWith(items);
return items;
}
}
}


