Offset Polyline

theswamp

    1. using System;

      1. using System.Collections.Generic;

      2. using System.Linq;

      3. using Autodesk.AutoCAD.DatabaseServices;

      4. namespace OffsetPolylineSample

      5. {

      6. /// <summary>

      7. /// Provides the Offset() extension method for the Polyline type

      8. /// </summary>

      9. public static class PolylineExtension

      10. {

      11. /// <summary>

      12. /// Enumeration of offset side options

      13. /// </summary>

      14. public enum OffsetSide { In, Out, Left, Right, Both }

      15. /// <summary>

      16. /// Offset the source polyline to specified side(s).

      17. /// </summary>

      18. /// <param name="source">The polyline to be offseted.</param>

      19. /// <param name="offsetDist">The offset distance.</param>

      20. /// <param name="side">The offset side(s).</param>

      21. /// <returns>A polyline sequence resulting from the offset of the source polyline.</returns>

      22. public static IEnumerable<Polyline> Offset(this Polyline source, double offsetDist, OffsetSide side)

      23. {

      24. offsetDist = Math.Abs(offsetDist);

      25. IEnumerable<Polyline> offsetRight = source.GetOffsetCurves(offsetDist).Cast<Polyline>();

      26. double areaRight = offsetRight.Select(pline => pline.Area).Sum();

      27. IEnumerable<Polyline> offsetLeft = source.GetOffsetCurves(-offsetDist).Cast<Polyline>();

      28. double areaLeft = offsetLeft.Select(pline => pline.Area).Sum();

      29. switch (side)

      30. {

      31. case OffsetSide.In:

      32. if (areaRight < areaLeft)

      33. {

      34. offsetLeft.Dispose();

      35. return offsetRight;

      36. }

      37. else

      38. {

      39. offsetRight.Dispose();

      40. return offsetLeft;

      41. }

      42. case OffsetSide.Out:

      43. if (areaRight < areaLeft)

      44. {

      45. offsetRight.Dispose();

      46. return offsetLeft;

      47. }

      48. else

      49. {

      50. offsetLeft.Dispose();

      51. return offsetRight;

      52. }

      53. case OffsetSide.Left:

      54. offsetRight.Dispose();

      55. return offsetLeft;

      56. case OffsetSide.Right:

      57. offsetLeft.Dispose();

      58. return offsetRight;

      59. case OffsetSide.Both:

      60. return offsetRight.Concat(offsetLeft);

      61. default:

      62. return null;

      63. }

      64. }

      65. private static void Dispose(this IEnumerable<Polyline> plines)

      66. {

      67. foreach (Polyline pline in plines)

      68. {

      69. pline.Dispose();

      70. }

      71. }

      72. }

      73. }

      74. using Autodesk.AutoCAD.ApplicationServices;

      75. using Autodesk.AutoCAD.DatabaseServices;

      76. using Autodesk.AutoCAD.EditorInput;

      77. using Autodesk.AutoCAD.Runtime;

      78. namespace OffsetPolylineSample

      79. {

      80. public class CommandMethods

      81. {

      82. [CommandMethod("Test", CommandFlags.Modal)]

      83. public void Test()

      84. {

      85. Document doc = Application.DocumentManager.MdiActiveDocument;

      86. Database db = doc.Database;

      87. Editor ed = doc.Editor;

      88. PromptDistanceOptions pdo =

      89. new PromptDistanceOptions("\nSpecify the offset distance: ");

      90. pdo.AllowZero = false;

      91. PromptDoubleResult pdr = ed.GetDistance(pdo);

      92. if (pdr.Status != PromptStatus.OK) return;

      93. double offsetDist = pdr.Value;

      94. PromptKeywordOptions pko =

      95. new PromptKeywordOptions("\nEnter the offset side [In/Out/Left/Right/Both]", "In Out Left Right Both");

      96. PromptResult pr = ed.GetKeywords(pko);

      97. if (pr.Status != PromptStatus.OK) return;

      98. PolylineExtension.OffsetSide side;

      99. switch (pr.StringResult)

      100. {

      101. case "In": side = PolylineExtension.OffsetSide.In; break;

      102. case "Out": side = PolylineExtension.OffsetSide.Out; break;

      103. case "Left": side = PolylineExtension.OffsetSide.Left; break;

      104. case "Right": side = PolylineExtension.OffsetSide.Right; break;

      105. default: side = PolylineExtension.OffsetSide.Both; break;

      106. }

      107. PromptEntityOptions peo = new PromptEntityOptions("\nSelect a polyline: ");

      108. peo.SetRejectMessage("Only a polyline !");

      109. peo.AddAllowedClass(typeof(Polyline), true);

      110. using (Transaction tr = db.TransactionManager.StartTransaction())

      111. {

      112. BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);

      113. while (true)

      114. {

      115. PromptEntityResult per = ed.GetEntity(peo);

      116. if (per.Status != PromptStatus.OK) break;

      117. Polyline pline = (Polyline)tr.GetObject(per.ObjectId, OpenMode.ForRead);

      118. foreach (Polyline pl in pline.Offset(offsetDist, side))

      119. {

      120. btr.AppendEntity(pl);

      121. tr.AddNewlyCreatedDBObject(pl, true);

      122. }

      123. db.TransactionManager.QueueForGraphicsFlush();

      124. }

      125. tr.Commit();

      126. }

      127. }

      128. }

      129. }

      130. using System;

      131. using System.Collections.Generic;

      132. using System.Linq;

      133. using Autodesk.AutoCAD.DatabaseServices;

      134. namespace OffsetPolylineSample

      135. {

      136. /// <summary>

      137. /// Provides the Offset() extension method for the Polyline type

      138. /// </summary>

      139. public static class PolylineExtension

      140. {

      141. /// <summary>

      142. /// Enumeration of offset side options

      143. /// </summary>

      144. public enum OffsetSide

      145. {

      146. In, Out, Left, Right, Both

      147. }

      148. /// <summary>

      149. /// Offset the source polyline to specified side(s).

      150. /// </summary>

      151. /// <param name="source">The polyline to be offseted.</param>

      152. /// <param name="offsetDist">The offset distance.</param>

      153. /// <param name="side">The offset side(s).</param>

      154. /// <returns>A polyline sequence resulting from the offset of the source polyline.</returns>

      155. public static IEnumerable<Polyline> Offset( this Polyline source, double offsetDist, OffsetSide side )

      156. {

      157. offsetDist = Math.Abs( offsetDist );

      158. using( var plines = new DisposableSet<Polyline>() )

      159. {

      160. IEnumerable<Polyline> offsetRight = source.GetOffsetCurves( offsetDist ).Cast<Polyline>();

      161. plines.AddRange( offsetRight );

      162. IEnumerable<Polyline> offsetLeft = source.GetOffsetCurves( -offsetDist ).Cast<Polyline>();

      163. plines.AddRange( offsetLeft );

      164. double areaRight = offsetRight.Select( pline => pline.Area ).Sum();

      165. double areaLeft = offsetLeft.Select( pline => pline.Area ).Sum();

      166. switch( side )

      167. {

      168. case OffsetSide.In:

      169. if( areaRight < areaLeft )

      170. {

      171. plines.RemoveRange( offsetRight );

      172. return offsetRight;

      173. }

      174. else

      175. {

      176. plines.RemoveRange( offsetLeft );

      177. return offsetLeft;

      178. }

      179. case OffsetSide.Out:

      180. if( areaRight < areaLeft )

      181. {

      182. plines.RemoveRange( offsetLeft );

      183. return offsetLeft;

      184. }

      185. else

      186. {

      187. plines.RemoveRange( offsetRight );

      188. return offsetRight;

      189. }

      190. case OffsetSide.Left:

      191. plines.RemoveRange( offsetLeft );

      192. return offsetLeft;

      193. case OffsetSide.Right:

      194. plines.RemoveRange( offsetRight );

      195. return offsetRight;

      196. case OffsetSide.Both:

      197. plines.Clear();

      198. return offsetRight.Concat( offsetLeft );

      199. default:

      200. return null;

      201. }

      202. }

      203. }

      204. }

      205. public class DisposableSet<T> : HashSet<T>, IDisposable where T: IDisposable

      206. {

      207. public void Dispose()

      208. {

      209. System.Exception last = null;

      210. foreach( T item in this )

      211. {

      212. if( item != null )

      213. {

      214. try

      215. {

      216. item.Dispose();

      217. }

      218. catch( System.Exception ex )

      219. {

      220. last = last ?? ex;

      221. }

      222. }

      223. }

      224. this.Clear();

      225. if( last != null )

      226. throw last;

      227. }

      228. public void AddRange( IEnumerable<T> items )

      229. {

      230. foreach( T item in items )

      231. {

      232. if( item == null )

      233. throw new ArgumentNullException( "element" );

      234. base.Add( item );

      235. }

      236. }

      237. public void RemoveRange( IEnumerable<T> items )

      238. {

      239. foreach( T item in items )

      240. {

      241. if( item != null )

      242. base.Remove( item );

      243. }

      244. }

      245. }

      246. }

      247. using System;

      248. using System.Collections.Generic;

      249. using System.Linq;

      250. using Autodesk.AutoCAD.DatabaseServices;

      251. namespace OffsetPolylineSample

      252. {

      253. /// <summary>

      254. /// Provides the Offset() extension method for the Polyline type

      255. /// </summary>

      256. public static class PolylineExtension

      257. {

      258. /// <summary>

      259. /// Enumeration of offset side options

      260. /// </summary>

      261. public enum OffsetSide

      262. {

      263. In, Out, Left, Right, Both

      264. }

      265. /// <summary>

      266. /// Offset the source polyline to specified side(s).

      267. /// </summary>

      268. /// <param name="source">The polyline to be offseted.</param>

      269. /// <param name="offsetDist">The offset distance.</param>

      270. /// <param name="side">The offset side(s).</param>

      271. /// <returns>A polyline sequence resulting from the offset of the source polyline.</returns>

      272. public static IEnumerable<Polyline> Offset( this Polyline source, double offsetDist, OffsetSide side )

      273. {

      274. offsetDist = Math.Abs( offsetDist );

      275. using( var plines = new DisposableSet<Polyline>() )

      276. {

      277. IEnumerable<Polyline> offsetRight = source.GetOffsetCurves( offsetDist ).Cast<Polyline>();

      278. plines.AddRange( offsetRight );

      279. IEnumerable<Polyline> offsetLeft = source.GetOffsetCurves( -offsetDist ).Cast<Polyline>();

      280. plines.AddRange( offsetLeft );

      281. double areaRight = offsetRight.Select( pline => pline.Area ).Sum();

      282. double areaLeft = offsetLeft.Select( pline => pline.Area ).Sum();

      283. switch( side )

      284. {

      285. case OffsetSide.In:

      286. return plines.RemoveRange(

      287. areaRight < areaLeft ? offsetRight : offsetLeft );

      288. case OffsetSide.Out:

      289. return plines.RemoveRange(

      290. areaRight < areaLeft ? offsetLeft : offsetRight );

      291. case OffsetSide.Left:

      292. return plines.RemoveRange( offsetLeft );

      293. case OffsetSide.Right:

      294. return plines.RemoveRange( offsetRight );

      295. case OffsetSide.Both:

      296. plines.Clear();

      297. return offsetRight.Concat( offsetLeft );

      298. default:

      299. return null;

      300. }

      301. }

      302. }

      303. }

      304. public interface IDisposableCollection<T> : ICollection<T>, IDisposable

      305. where T : IDisposable

      306. {

      307. void AddRange( IEnumerable<T> items );

      308. IEnumerable<T> RemoveRange( IEnumerable<T> items );

      309. }

      310. public class DisposableSet<T> : HashSet<T>, IDisposableCollection<T>

      311. where T: IDisposable

      312. {

      313. public DisposableSet()

      314. {

      315. }

      316. public DisposableSet( IEnumerable<T> items )

      317. {

      318. AddRange( items );

      319. }

      320. public void Dispose()

      321. {

      322. if( base.Count > 0 )

      323. {

      324. System.Exception last = null;

      325. var list = this.ToList();

      326. this.Clear();

      327. foreach( T item in list )

      328. {

      329. if( item != null )

      330. {

      331. try

      332. {

      333. item.Dispose();

      334. }

      335. catch( System.Exception ex )

      336. {

      337. last = last ?? ex;

      338. }

      339. }

      340. }

      341. if( last != null )

      342. throw last;

      343. }

      344. }

      345. public void AddRange( IEnumerable<T> items )

      346. {

      347. if( items == null )

      348. throw new ArgumentNullException( "items" );

      349. base.UnionWith( items );

      350. }

      351. public IEnumerable<T> RemoveRange( IEnumerable<T> items )

      352. {

      353. if( items == null )

      354. throw new ArgumentNullException( "items" );

      355. base.ExceptWith( items );

      356. return items;

      357. }

      358. }

      359. }