Reputation: 91
I am trying to select all polylines of a specific layer and then join them with the normal autocad _JOIN command. For some reason i just cant get it to work.
The selectionset is properly found as i could loop through it and change the color of the polyline (just did that for testing purpose)
What am i missing/doing wrong here?
[CommandMethod("JOINPOLY",
CommandFlags.UsePickSet |
CommandFlags.Redraw |
CommandFlags.Modal)]
public void SelectAllPolylineByLayer()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
try
{
// create the typevalue (criteria what should be selected)
TypedValue[] tvs = new TypedValue[] {
new TypedValue(Convert.ToInt32(DxfCode.Operator), "<and"),
new TypedValue(Convert.ToInt32(DxfCode.LayerName), "Test unlocked"),
new TypedValue(Convert.ToInt32(DxfCode.Operator), "<or"),
new TypedValue(Convert.ToInt32(DxfCode.Start), "POLYLINE"),
new TypedValue(Convert.ToInt32(DxfCode.Start), "LWPOLYLINE"),
new TypedValue(Convert.ToInt32(DxfCode.Start), "POLYLINE2D"),
new TypedValue(Convert.ToInt32(DxfCode.Start), "POLYLINE3d"),
new TypedValue(Convert.ToInt32(DxfCode.Operator), "or>"),
new TypedValue(Convert.ToInt32(DxfCode.Operator), "and>")
};
// create a selectionfilter out of our created typevalue
SelectionFilter oSf = new SelectionFilter(tvs);
PromptSelectionResult selRes = ed.SelectAll(oSf);
// if there is a problemw ith the promtselection stop here
if (selRes.Status != PromptStatus.OK)
{
ed.WriteMessage("\nError in getting the selectAll");
return;
}
SelectionSet ss = selRes.Value;
ed.Command("_JOIN", ss, "");
tr.Commit();
}
//Catch the error and write the errormessage
catch (System.Exception ex)
{
ed.WriteMessage(Convert.ToString(ex));
}
}
}
Upvotes: 2
Views: 4102
Reputation: 91
if anyone still cares about that this was the end result i came up with in the end i save all entities into a list of a class that has entity, startpoint and endpoint of the polylines saved
then i compare if start and endpoints of the elements in list match and join them with entity.join()
/// <summary>
/// Gets a layerName and tries to join all polylines on the given layer
/// sends back a little log message to display
/// </summary>
/// <param name="layerName"></param>
/// <returns></returns>
public static string JoinPolylineOnLayer(Database db, string layerName)
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
TypedValue[] tvs = null;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
LayerTable layerTable = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead);
try
{
// get layerid of the selected layer
var layerId = layerTable[layerName];
// open layer table record with write privileges
// if the layer is locked return with an error message that the layer cant be deleted
LayerTableRecord layer = (LayerTableRecord)tr.GetObject(layerId, OpenMode.ForWrite);
if (layer.IsLocked)
return "' cannot be merged(locked).";
// create the typevalue (criteria what should be selected)
tvs = new TypedValue[] {
new TypedValue(Convert.ToInt32(DxfCode.Operator), "<and"),
new TypedValue(Convert.ToInt32(DxfCode.LayerName), layerName),
new TypedValue(Convert.ToInt32(DxfCode.Operator), "<or"),
new TypedValue(Convert.ToInt32(DxfCode.Start), "POLYLINE"),
new TypedValue(Convert.ToInt32(DxfCode.Start), "LWPOLYLINE"),
new TypedValue(Convert.ToInt32(DxfCode.Start), "POLYLINE2D"),
new TypedValue(Convert.ToInt32(DxfCode.Start), "POLYLINE3D"),
new TypedValue(Convert.ToInt32(DxfCode.Operator), "or>"),
new TypedValue(Convert.ToInt32(DxfCode.Operator), "and>")
};
// create a list of the entities
List<PolylineClass> entities = FillListOfEntities(tvs, tr, ed);
for (int i = entities.Count - 1; i >= 0; i--)
{
for (int j = i - 1; j >= 0; j--)
{
try
{
// check if start/endpoints are the same
// if they are join them and reset the loops and start again
if ((entities[i].StartPoint == entities[j].StartPoint) ||
(entities[i].StartPoint == entities[j].EndPoint) ||
(entities[i].EndPoint == entities[j].StartPoint) ||
(entities[i].EndPoint == entities[j].EndPoint))
{
Entity srcPLine = entities[i].Ent;
Entity addPLine = entities[j].Ent;
// join both entities
srcPLine.UpgradeOpen();
srcPLine.JoinEntity(addPLine);
// delete the joined entity
addPLine.UpgradeOpen();
entities.RemoveAt(j);
addPLine.Erase();
// set new start and end point of the joined polyline
entities[i - 1] = new PolylineClass(srcPLine, GetStartPointData(srcPLine), GetEndPointData(srcPLine));
// reset i to the start (as it has changed)
i = entities.Count;
j = 0;
}
}
catch (System.Exception ex)
{
ed.WriteMessage("\nError: n{0}", ex.Message);
}
}
}
tr.Commit();
return "' have been joined";
}
//Catch the error and write the errormessage
catch (System.Exception ex)
{
return Convert.ToString(ex);
}
}
}
/// <summary>
/// Function to fill the entities list with a give TypedValue
/// </summary>
/// <param name="tvs"></param>
/// <param name="tr"></param>
/// <param name="ed"></param>
/// <returns></returns>
private static List<PolylineClass> FillListOfEntities(TypedValue[] tvs, Transaction tr, Editor ed)
{
SelectionFilter oSf = new SelectionFilter(tvs);
PromptSelectionResult selRes = ed.SelectAll(oSf);
// if there is a problemw ith the promtselection stop here
if (selRes.Status != PromptStatus.OK)
{
return null;
}
// declare a list and fill it with all elements from our selectionfilter
List<PolylineClass> entities = new List<PolylineClass>();
foreach (ObjectId obj in selRes.Value.GetObjectIds())
{
Entity ent = tr.GetObject(obj, OpenMode.ForRead) as Entity;
entities.Add(new PolylineClass(ent, GetStartPointData(ent), GetEndPointData(ent)));
}
return entities;
}
/// <summary>
/// Function to get the startpoint coordinates of a polyline
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
private static Point3d GetStartPointData(Entity obj)
{
// If a "lightweight" (or optimized) polyline
Polyline lwp = obj as Polyline;
if (lwp != null)
{
return new Point3d(lwp.GetPoint2dAt(0).X, lwp.GetPoint2dAt(0).Y, lwp.Elevation);
}
else
{
// If an old-style, 2D polyline
Polyline2d p2d = obj as Polyline2d;
if (p2d != null)
{
return new Point3d (p2d.StartPoint.X, p2d.StartPoint.Y, p2d.Elevation);
}
else
{
// If an old-style, 3D polyline
Polyline3d p3d = obj as Polyline3d;
if (p3d != null)
{
return p3d.StartPoint;
}
}
}
return new Point3d(0, 0, 0);
}
/// <summary>
/// Function to get the endpoint coordinates of a polyline
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
private static Point3d GetEndPointData(Entity obj)
{
// If a "lightweight" (or optimized) polyline
Polyline lwp = obj as Polyline;
if (lwp != null)
{
return new Point3d(lwp.GetPoint2dAt(lwp.NumberOfVertices - 1).X, lwp.GetPoint2dAt(lwp.NumberOfVertices - 1).Y, lwp.Elevation);
}
else
{
// If an old-style, 2D polyline
Polyline2d p2d = obj as Polyline2d;
if (p2d != null)
{
return new Point3d(p2d.EndPoint.X, p2d.EndPoint.Y, p2d.Elevation);
}
else
{
// If an old-style, 3D polyline
Polyline3d p3d = obj as Polyline3d;
if (p3d != null)
{
return p3d.EndPoint;
}
}
}
return new Point3d(0, 0, 0);
}
Upvotes: 3
Reputation: 13296
The right way to do that (if you are using a version of AutoCAD >= 2013) is to use the Polyline.JoinEntities
method.
Don't forget to read the doc :
Polyline.JoinEntities requires the given entities to be other, unclosed Polyline or Polyline2d, Line, and/or Arc entities, which share common start or end points.
To handle the 3D polylines, you have to convert them to lines/2D polylines (of course all the entities must be in the same plane).
There is a sample here: http://adndevblog.typepad.com/autocad/2012/05/joining-2d-3d-polylines.html
Upvotes: 1
Reputation: 91
the editor command seems to be different from the client join
as workaround i am using the following now:
doc.SendStringToExecute("._JOIN\n_p\n\n", true, false, false);
i am not 100% happy with it but well, that's what i have to go with for now.
Upvotes: 1