Message 1 of 9
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
Hi,
I want to streatch multiple segments of closed polygon using C#.net as we can streatch with AutoCAD command.
Solved! Go to Solution.
Hi,
I want to streatch multiple segments of closed polygon using C#.net as we can streatch with AutoCAD command.
Solved! Go to Solution.
I will check and let you know
Please condiser Jig while streatching the feature.
Hi,
Here's a PolylineStretchJig example (the 'indexes' parameter contains the polyline indexes to stretch).
class PolylineStretchJig : EntityJig
{
Polyline _pline;
Plane _plane;
Dictionary<int, Point2d> _vertices;
Point3d _basePoint, _dragPoint;
public PolylineStretchJig(Polyline pline, Point3d basePoint, List<int> indexes) : base(pline)
{
_pline = pline;
_plane = new Plane(Point3d.Origin, pline.Normal);
_vertices = indexes.ToDictionary(i => i, i => pline.GetPoint2dAt(i));
_basePoint = basePoint;
}
protected override SamplerStatus Sampler(JigPrompts prompts)
{
var jppo = new JigPromptPointOptions()
{
Message = "\nSpecify second point: ",
BasePoint = _basePoint,
UseBasePoint = true
};
var result = prompts.AcquirePoint(jppo);
if (result.Value.IsEqualTo(_dragPoint))
return SamplerStatus.NoChange;
_dragPoint = result.Value;
return SamplerStatus.OK;
}
protected override bool Update()
{
Vector2d vector = (_dragPoint - _basePoint).Convert2d(_plane);
foreach (var vertex in _vertices)
{
_pline.SetPointAt(vertex.Key, vertex.Value + vector);
}
return true;
}
}
A testing command (should work as expected when View == Top).
public void Test()
{
var doc = Application.DocumentManager.MdiActiveDocument;
var db = doc.Database;
var ed = doc.Editor;
var promptEntityOptions = new PromptEntityOptions("\nSelect Polyline to strech: ");
promptEntityOptions.SetRejectMessage("\nSelected object is not a polyline.");
promptEntityOptions.AddAllowedClass(typeof(Polyline), true);
var promptEntityResult = ed.GetEntity(promptEntityOptions);
if (promptEntityResult.Status != PromptStatus.OK)
return;
var promptPointResult = ed.GetPoint("\nSelect vertices to stretch: ");
if (promptPointResult.Status != PromptStatus.OK)
return;
var promptCornerResult = ed.GetCorner("\nSpecify the opposite corner", promptPointResult.Value);
if (promptCornerResult.Status != PromptStatus.OK)
return;
using (var tr = db.TransactionManager.StartTransaction())
{
var ucs = ed.CurrentUserCoordinateSystem;
var extents = new Extents3d();
extents.AddPoint(promptPointResult.Value);
extents.AddPoint(promptCornerResult.Value);
extents.TransformBy(ucs);
var pline = (Polyline)tr.GetObject(promptEntityResult.ObjectId, OpenMode.ForWrite);
var indexes = new List<int>();
bool IsPointInside(Point3d pt) =>
extents.MinPoint.X <= pt.X &&
extents.MinPoint.Y <= pt.Y &&
extents.MinPoint.Z <= pt.Z &&
pt.X <= extents.MaxPoint.X &&
pt.Y <= extents.MaxPoint.Y &&
pt.Z <= extents.MaxPoint.Z;
for (int i = 0; i < pline.NumberOfVertices; i++)
{
if (IsPointInside(pline.GetPoint3dAt(i)))
indexes.Add(i);
}
if (indexes.Count == 0)
return;
promptPointResult = ed.GetPoint("\nSpecify base point: ");
if (promptPointResult.Status != PromptStatus.OK)
return;
var basePoint = promptPointResult.Value.TransformBy(ucs);
var jig = new PolylineStretchJig(pline, basePoint, indexes);
var promptResult = ed.Drag(jig);
if (promptResult.Status != PromptStatus.OK)
return;
tr.Commit();
}
}
Hi @_gile, aside from performance reasons with a large number of vertices, I can think of several other reasons why I would prefer using Entity.MoveStretchPointsAt() verses manually moving each vertex as per your example.
Those other reasons are related to hatching: associative dimensions; and more generally, involvement in any kind of associative network where other objects have a dependence on the polyline.
Also, with Entity.MoveStretchPointsAt(), the solution would stretch any Entity, rather than just polylines.
Here is your example, hastily refactored to work with any Entity (untested):
using System;
using System.Linq;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
/// <summary>
/// Gile's example, refactored to stretch
/// any type of Entity that can be stretched.
/// </summary>
namespace Examples
{
class EntityStretchJig : EntityJig
{
Entity entity;
IntegerCollection indices;
Point3d basePoint;
Point3d lastPoint;
Point3d samplePoint;
public EntityStretchJig(Entity entity, Point3d basePoint, IntegerCollection indexes)
: base(entity)
{
if(entity == null)
throw new ArgumentNullException(nameof(entity));
if(!entity.IsWriteEnabled)
throw new Autodesk.AutoCAD.Runtime.Exception(ErrorStatus.NotOpenForWrite);
Point3dCollection stretchPoints = new Point3dCollection();
entity.GetStretchPoints(stretchPoints);
if(stretchPoints.Count == 0)
throw new ArgumentException("Can't stretch the given entity");
if(indices.Count > stretchPoints.Count)
throw new ArgumentException("Invalid index array");
if(indices.Cast<int>().Max() >= stretchPoints.Count)
throw new IndexOutOfRangeException();
this.entity = entity;
this.indices = indexes;
this.basePoint = basePoint;
this.lastPoint = basePoint;
}
protected override SamplerStatus Sampler(JigPrompts prompts)
{
var jppo = new JigPromptPointOptions()
{
Message = "\nSpecify second point: ",
BasePoint = basePoint,
UseBasePoint = true
};
var result = prompts.AcquirePoint(jppo);
if(result.Status != PromptStatus.OK)
return SamplerStatus.Cancel;
if(result.Value.IsEqualTo(lastPoint))
return SamplerStatus.NoChange;
samplePoint = result.Value;
return SamplerStatus.OK;
}
protected override bool Update()
{
entity.MoveStretchPointsAt(indices, samplePoint - lastPoint);
lastPoint = samplePoint;
return true;
}
}
public static class TestCase
{
[CommandMethod("MYSTRETCH")]
public static void Test()
{
var doc = Application.DocumentManager.MdiActiveDocument;
var db = doc.Database;
var ed = doc.Editor;
var peo = new PromptEntityOptions("\nSelect entity to strech: ");
var per = ed.GetEntity(peo);
if(per.Status != PromptStatus.OK)
return;
var ppr = ed.GetPoint("\nSelect vertices to stretch: ");
if(ppr.Status != PromptStatus.OK)
return;
var pcr = ed.GetCorner("\nSpecify the opposite corner", ppr.Value);
if(pcr.Status != PromptStatus.OK)
return;
var ucs = ed.CurrentUserCoordinateSystem;
var extents = new Extents3d();
extents.AddPoint(ppr.Value);
extents.AddPoint(pcr.Value);
extents.TransformBy(ucs);
Point3dCollection stretchPoints = new Point3dCollection();
using(var tr = db.TransactionManager.StartTransaction())
{
var entity = (Entity)tr.GetObject(per.ObjectId, OpenMode.ForRead);
entity.GetStretchPoints(stretchPoints);
tr.Commit();
}
/// Let's try to avoid user interatiion inside an
/// active transaction, to avoid undesired side-
/// effects of aborting the transaction (e.g.,
/// undoing transparent pans/zooms, etc.).
if(stretchPoints.Count == 0)
{
ed.WriteMessage("\nCan't stretch selected entity.");
return;
}
IntegerCollection list = new IntegerCollection(stretchPoints.Count);
for(int i = 0; i < stretchPoints.Count; i++)
{
if(extents.Contains(stretchPoints[i]))
list.Add(i);
}
if(list.Count == 0)
return;
ppr = ed.GetPoint("\nSpecify base point: ");
if(ppr.Status != PromptStatus.OK)
return;
var basePoint = ppr.Value.TransformBy(ucs);
using(var tr = db.TransactionManager.StartTransaction())
{
var entity = (Entity)tr.GetObject(per.ObjectId, OpenMode.ForWrite);
var jig = new EntityStretchJig(entity, basePoint, list);
var promptResult = ed.Drag(jig);
if(promptResult.Status != PromptStatus.OK)
return;
tr.Commit();
}
}
}
public static class NoCopyAndPasteExtensions
{
public static bool Contains(this Extents3d extents, Point3d pt)
{
Point3d min = extents.MinPoint;
Point3d max = extents.MaxPoint;
return min.X <= pt.X && min.Y <= pt.Y && min.Z <= pt.Z
&& pt.X <= max.X && pt.Y <= max.Y && pt.Z <= max.Z;
}
}
}
I didn't know this method.
Thanks for make me (us) discover it and for the code sample.
There's a little mistake (typo?) in the EntityStretchJig constructor: 'indices' instead of 'indexes' lines 36 and 38.
Hi @_gile, thanks for pointing out that bug. The last thing I did before copying it was to move all the assignments to the bottom of the constructor, not realizing that was a mistake.
using System;
using System.Linq;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
/// <summary>
/// Gile's example, refactored to stretch
/// any type of Entity that can be stretched.
/// </summary>
namespace Examples
{
class EntityStretchJig : EntityJig
{
Entity entity;
IntegerCollection indices;
Point3d basePoint;
Point3d lastPoint;
Point3d samplePoint;
public EntityStretchJig(Entity entity, Point3d basePoint, IntegerCollection indexes)
: base(entity)
{
if(entity == null)
throw new ArgumentNullException(nameof(entity));
if(indexes == null)
throw new ArgumentNullException(nameof(indexes));
if(!entity.IsWriteEnabled)
throw new Autodesk.AutoCAD.Runtime.Exception(ErrorStatus.NotOpenForWrite);
Point3dCollection stretchPoints = new Point3dCollection();
entity.GetStretchPoints(stretchPoints);
if(stretchPoints.Count == 0)
throw new ArgumentException("Can't stretch the given entity");
if(indexes.Count > stretchPoints.Count)
throw new ArgumentException("Invalid index array");
if(indexes.Cast<int>().Max() >= stretchPoints.Count)
throw new IndexOutOfRangeException();
this.indices = indexes;
this.entity = entity;
this.basePoint = basePoint;
this.lastPoint = basePoint;
}
protected override SamplerStatus Sampler(JigPrompts prompts)
{
var jppo = new JigPromptPointOptions()
{
Message = "\nSpecify second point: ",
BasePoint = basePoint,
UseBasePoint = true
};
var result = prompts.AcquirePoint(jppo);
if(result.Status != PromptStatus.OK)
return SamplerStatus.Cancel;
if(result.Value.IsEqualTo(lastPoint))
return SamplerStatus.NoChange;
samplePoint = result.Value;
return SamplerStatus.OK;
}
protected override bool Update()
{
entity.MoveStretchPointsAt(indices, samplePoint - lastPoint);
lastPoint = samplePoint;
return true;
}
}
public static class TestCase
{
[CommandMethod("MYSTRETCH")]
public static void Test()
{
var doc = Application.DocumentManager.MdiActiveDocument;
var db = doc.Database;
var ed = doc.Editor;
var peo = new PromptEntityOptions("\nSelect entity to strech: ");
var per = ed.GetEntity(peo);
if(per.Status != PromptStatus.OK)
return;
var ppr = ed.GetPoint("\nSelect vertices to stretch: ");
if(ppr.Status != PromptStatus.OK)
return;
var pcr = ed.GetCorner("\nSpecify the opposite corner", ppr.Value);
if(pcr.Status != PromptStatus.OK)
return;
var ucs = ed.CurrentUserCoordinateSystem;
var extents = new Extents3d();
extents.AddPoint(ppr.Value);
extents.AddPoint(pcr.Value);
extents.TransformBy(ucs);
Point3dCollection stretchPoints = new Point3dCollection();
using(var tr = db.TransactionManager.StartTransaction())
{
var entity = (Entity)tr.GetObject(per.ObjectId, OpenMode.ForRead);
entity.GetStretchPoints(stretchPoints);
tr.Commit();
}
/// Try to avoid user interatiion inside an
/// active transaction, to avoid undesired side-
/// effects of aborting the transaction (e.g.,
/// undoing transparent pans/zooms, etc.).
if(stretchPoints.Count == 0)
{
ed.WriteMessage("\nCan't stretch selected entity.");
return;
}
IntegerCollection list = new IntegerCollection(stretchPoints.Count);
for(int i = 0; i < stretchPoints.Count; i++)
{
if(extents.Contains(stretchPoints[i]))
list.Add(i);
}
if(list.Count == 0)
return;
ppr = ed.GetPoint("\nSpecify base point: ");
if(ppr.Status != PromptStatus.OK)
return;
var basePoint = ppr.Value.TransformBy(ucs);
using(var tr = db.TransactionManager.StartTransaction())
{
var entity = (Entity)tr.GetObject(per.ObjectId, OpenMode.ForWrite);
var jig = new EntityStretchJig(entity, basePoint, list);
var promptResult = ed.Drag(jig);
if(promptResult.Status != PromptStatus.OK)
return;
tr.Commit();
}
}
}
public static class NoCopyAndPasteExtensions
{
public static bool Contains(this Extents3d extents, Point3d pt)
{
Point3d min = extents.MinPoint;
Point3d max = extents.MaxPoint;
return min.X <= pt.X && min.Y <= pt.Y && min.Z <= pt.Z
&& pt.X <= max.X && pt.Y <= max.Y && pt.Z <= max.Z;
}
}
}
The code shared by @ActivistInvestor (message #7) is more robust. You should use it instead.