.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Copy Selection Set

5 REPLIES 5
Reply
Message 1 of 6
davidgarner
2212 Views, 5 Replies

Copy Selection Set

I have lisp code that looks like this.

(setq ss (ssget))
(command "COPY" ss "" "@" "@")

This allows the user to make a selection set, then the copy command is called on the selection set.

I need to do the same thing in .Net (C#)

I can get the selection set from the user with:
SelectionSet selection = Application.DocumentManager.MdiActiveDocument.Editor.GetSelection().Value

How can I invoke the copy command on the selection set contained in the "selection" variable?
5 REPLIES 5
Message 2 of 6
pellacad
in reply to: davidgarner

Greetings David,

I'm trying to do the same thing in VB.NET.

We're you ever able to use selection sets with ACAD commands?

I'm searching high and low...

I'll post any developments.

Pete
Message 3 of 6
_gile
in reply to: davidgarner

Hi,

IMO, using .NET as a script langage (calling native AutoCAD commands) is a nonsense.
Even LISP provides much more than this kinf of statements.

Anyway, you can convert your selection set into an ObjectId array:
selection.GetObjectIds
Then, iterate thru this array, get each objectId as entity and use the Clone() method to create a copy, add this copy to the current space (or another BlockTableRecord.

Here's a little example, the "Test" command prompt for a selection, a base point, a second point and calls the CopyMove method to copy the selection set and move the copied entities.

{code}[CommandMethod("Test")]
public void Test()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
Matrix3d ucs = ed.CurrentUserCoordinateSystem;
PromptSelectionResult psr = ed.GetSelection();
if (psr.Status != PromptStatus.OK)
return;
PromptPointResult ppr = ed.GetPoint("\nBase point: ");
if (ppr.Status != PromptStatus.OK)
return;
Point3d basePoint = ppr.Value;
PromptPointOptions ppo = new PromptPointOptions("\nSecond point: ");
ppo.BasePoint = basePoint;
ppo.UseBasePoint = true;
ppr = ed.GetPoint(ppo);
if (ppr.Status != PromptStatus.OK)
return;
Vector3d disp = basePoint.TransformBy(ucs).GetVectorTo(ppr.Value.TransformBy(ucs));
ObjectId[] ss = psr.Value.GetObjectIds();
try
{
CopyMove(ss, disp);
}
catch (System.Exception ex)
{
ed.WriteMessage("Error: " + ex.Message);
}
}

private void CopyMove(ObjectId[] ss, Vector3d disp)
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
foreach (ObjectId id in ss)
{
Entity ent = (Entity)tr.GetObject(id, OpenMode.ForWrite, false);
Entity copiedEnt = (Entity)ent.Clone();
btr.AppendEntity(copiedEnt);
tr.AddNewlyCreatedDBObject(copiedEnt, true);
ent.TransformBy(Matrix3d.Displacement(disp));
}
tr.Commit();
}
}{code}


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 4 of 6
Anonymous
in reply to: davidgarner

Ummmm.... Applications generally don't call Clone() directly to copy
objects.

Clone() creates a *shallow* clone of an object, which means that things like
subentities and other owned objects (like extension dictionaries and their
contents) are not also cloned, as they would be if you used the AutoCAD COPY
command.

For example, if you tried your code on a 'heavy' polyline or a block
reference with attributes, odds are that you would end up with a corrupt
drawing, polylines with no vertices, block insertions with no attributes,
multiply-owned objects, and other unexpected/undesired results.

There is also the matter of object id translation that occurs when multiple
objects are copied, and some of those objects hold a reference other objects
that are also being copied. In that case, a translation applied to all
object id references in the referencing objects, such that clones of those
referencing objects will be modified to reference the clones of the
referenced objects.

For example, if you have object 'a' and object 'b', where 'a' holds a
reference to 'b', and you DeepClone() both of them resulting in 'c' and 'd'
respectively, the clone of 'a' (c) will be modified to reference the clone
of 'b' (d).

The DeepClone() method of the database is generally how we 'copy' objects.
You can use it to copy objects within the same owner, as well as to another
owner. It takes care of all of the aforementioned (and other) gory details.
You can also handle the DeepClone-related events of the Database to operate
on the cloned objects as well, to transform them, or whatever else you need
to do.

An example of using DeepClone-related events can be found in this file:

http://www.caddzone.com/BlockExplodeHelper.cs

--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD
Supporting AutoCAD 2000 through 2010

http://www.acadxtabs.com

Email: string.Format("{0}@{1}.com", "tonyt", "caddzone");

<_gile> wrote in message news:6305533@discussion.autodesk.com...
Hi,

You can convert your selection set into an ObjectId array:
selection.GetObjectIds
Then, iterate thru this array, get each objectId as entity and use the
Clone() method to create a copy, add this copy to the current space (or
another BlockTableRecord.

Here's a little example, the "Test" command prompt for a selection, a base
point, a second point and calls the CopyMove method to copy the selection
set and move the copied entities.
Message 5 of 6
_gile
in reply to: davidgarner

Thank you Tony (one more time).

I used the statement shown in AutoCAD .NET Developer's Guide > Create and Edit AutoCAD Entities > Edit Named and 2D Objects > Copy Objects > Copy Object.

I made some tests with complex entities (block references with attributes, heavy polylines), with xdictionaries and xdatas too, but have no problem.

Anyway, I'll study what you provide.

So, this way would be safer ?

{code}private void CopyMove(ObjectIdCollection ids, Vector3d disp)
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
IdMapping idMap = new IdMapping();
db.DeepCloneObjects(ids, db.CurrentSpaceId, idMap, false);
foreach (IdPair pair in idMap)
{
if (pair.IsPrimary && pair.IsCloned)
{
Entity ent = (Entity)tr.GetObject(pair.Value, OpenMode.ForWrite, false);
ent.TransformBy(Matrix3d.Displacement(disp));
}
}
tr.Commit();
}
}{code}

Edited by: _gile on Dec 16, 2009 7:05 PM


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 6 of 6
Anonymous
in reply to: davidgarner

Ooops..

In case anyone is confused by it, I mistakenly refer to the
DeepCloneObjects() method, as the 'DeepClone()' method, which doesn't exist.

--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD
Supporting AutoCAD 2000 through 2010

http://www.acadxtabs.com

Email: string.Format("{0}@{1}.com", "tonyt", "caddzone");

<_gile> wrote in message news:6305560@discussion.autodesk.com...
Thank you Tony (one more time).

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost