Setting a Group of Layers Visible in a Viewport

Setting a Group of Layers Visible in a Viewport

mgorecki
Collaborator Collaborator
5,667 Views
51 Replies
Message 1 of 52

Setting a Group of Layers Visible in a Viewport

mgorecki
Collaborator
Collaborator

I have a dialog box that has 2 list boxes.  One box has the available layers in it, while the other will contain the selected layers.  I want to use those selected layers as a list of layers that will be visible in a particular viewport.  I have searched all over to find information on what kind of list I would need and how could I use the list with a viewport, but all I've found is info for one layer becoming visible.

I'm also looking into "FreezeLayersInViewport" but info sure seems limited.

Any help would be appreciated.

 

Thanks,

Mark

0 Likes
5,668 Views
51 Replies
Replies (51)
Message 41 of 52

mgorecki
Collaborator
Collaborator

Hi Chief,

How would I select the objects on a particular layer if that layer is not even visible at the time?

 

Thanks,

Mark

0 Likes
Message 42 of 52

Anonymous
Not applicable

Hi Mark,

 

I tried Editor.SelectAll() with a SelectionFilter and it didn't matter if the object were in view or not - well at least for AutoCAD 2012. In fact it even worked when I did so from paper space. Have you tried it?

 

This limitation does apply for some of the other Editor window selection methods.

 

Below is the code I tried.

 

Cheers,

Art

 

// Test command that changes all entities on layer zero to have red color.
[CommandMethod("SelectAllTest")]
public static void SelectAllTest() {
 
                    Document doc = Application.DocumentManager.MdiActiveDocument;
                    Database db = doc.Database;
                    Editor ed = doc.Editor;
 
                    // Selection filter to select only entities on layer zero.
                    TypedValue[] tvs = new TypedValue[] {
                                         new TypedValue((int)DxfCode.LayerName, "0") };
                    SelectionFilter sf = new SelectionFilter(tvs);
 
                    // SelectAll() using SelectionFilter.
                    PromptSelectionResult psr = ed.SelectAll(sf);
 
                    // Check prompt result.
                    if (psr.Status != PromptStatus.OK) {
                                        return;
                    }
                    if (psr.Value.Count == 0) {
                                        return;
                    }
 
                    using (Transaction tr = db.TransactionManager.StartTransaction()) {
 
                                        // Iterate selection.
                                        foreach (SelectedObject so in psr.Value) {
 
                                                             Entity ent = tr.GetObject(so.ObjectId, OpenMode.ForWrite) as Entity;
                                                             ent.ColorIndex = 1;        // Red color.
                                         }
 
                    tr.Commit();
                    }
}

 

 

 

0 Likes
Message 43 of 52

mgorecki
Collaborator
Collaborator

Hi Art,

Thanks, I'll be careful where I use selection sets.  I do remember this problem when I was using LiSP.  I had to put in a "zoom all" type command before the selection was made.

In the current case, the program will create a new blank layer, then copy the objects from a source layer to the newly created layer.  The source layer may not even be turned on.

 

Thanks,

Mark

0 Likes
Message 44 of 52

mgorecki
Collaborator
Collaborator

Hi Chief,

The users will be in PaperSpace when they run the program.  The objects will be in ModelSpace.  Will this be a problem?

 

Thanks,

Mark

0 Likes
Message 45 of 52

chiefbraincloud
Collaborator
Collaborator

No.  And it appears Art is correct, the "on screen" limitation does not seem to apply to the SelectAll method, but only the selection methods that use a window or fence.

Dave O.                                                                  Sig-Logos32.png
0 Likes
Message 46 of 52

mgorecki
Collaborator
Collaborator

Ok, I've updated my code so that the objects get copied from source layer to target layer.  Thank you Cheif and Art for all your help.

    Public Sub CopyObjectsToNewLayer(ByVal pageNumber As String, ByVal pageToCopy As String)
        Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
        Dim acCurDb As Database = acDoc.Database

        Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()

            ' Request for objects to be selected in the drawing area
            Dim myBlkTable As BlockTable = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead)
            Dim myBlkTableRec As BlockTableRecord
            Dim ed As Editor = acDoc.Editor
            Dim sourceLayer As String = "DETAIL_" & pageToCopy
            Dim targetLayer As String = "DETAIL_" & pageNumber

            ' Build a filter list so that only entities on the specified layer are selected
            Dim tvs As TypedValue() = New TypedValue(0) {New TypedValue(CInt(DxfCode.LayerName), sourceLayer)}
            Dim layerilter As New SelectionFilter(tvs)
            Dim sourceLayerPSR As PromptSelectionResult = ed.SelectAll(layerilter)

            myBlkTableRec = acTrans.GetObject(myBlkTable(BlockTableRecord.ModelSpace), OpenMode.ForWrite)

            ' Step through the objects in the selection set
            For Each SelectionSetObj As SelectedObject In sourceLayerPSR.Value
                ' Check to make sure a valid SelectedObject object was returned
                If Not IsDBNull(SelectionSetObj) Then
                    ' Open the selected object
                    Dim sourceEnt As Entity = acTrans.GetObject(SelectionSetObj.ObjectId, OpenMode.ForRead)
                    Dim entClone As Entity = TryCast(sourceEnt.Clone(), Entity)
                    entClone.Layer = targetLayer
                    '' Add the new object to the block table record and the transaction
                    myBlkTableRec.AppendEntity(entClone)
                    acTrans.AddNewlyCreatedDBObject(entClone, True)
                End If
            Next
            ' Save the new object to the database
            acTrans.Commit()
            acTrans.Dispose()
        End Using
    End Sub

 Take care,

Mark

0 Likes
Message 47 of 52

chiefbraincloud
Collaborator
Collaborator

There is one more possible pitfall with the selection.  If there are any entities in PaperSpace (any paper space, not just the active one) that are on the same layer, the will get selected also, and therefore your code would copy them into the Model Space.

 

The easiest way to correct that issue is to add another TypedValue (67,0) to your filter list.  That will restrict the selection to Model Space objects only.

Dave O.                                                                  Sig-Logos32.png
0 Likes
Message 48 of 52

mgorecki
Collaborator
Collaborator

Thanks for the info.  Where would I find this kind of information?  Is this similar to DXF properties?

0 Likes
Message 49 of 52

chiefbraincloud
Collaborator
Collaborator

Yes, they are referred to as DXF Group Codes.  I have a (very) old Lisp book, which has a list of them in the back.  Sometimes it is easier for me to find things in the Lisp book that proved difficult to find by looking at the DxfCode Enum in .NET.

 

In fact, in this case, the DxfCode Enum in .NET that corresponds to 67 is DxfCode.ViewportVisibility, which is incorrect, so I never would have found it through the object browser.

Dave O.                                                                  Sig-Logos32.png
0 Likes
Message 50 of 52

mgorecki
Collaborator
Collaborator

Ok, great.  Thanks again.

0 Likes
Message 51 of 52

Anonymous
Not applicable

The alternative way to do this is to iterate through the model space BlockTableRecord and clone entities from the source to target layer.

 

Refer to the code below.

 

I am not sure about the relative performance compared to the selection filter approach if you have a very large file with tons of model space entities. You might want to test this.

 

Art

 

 

public static void CopyObjectToNewLayer(string pageNumber, string pageToCopy) {

	Document doc = Application.DocumentManager.MdiActiveDocument;
	Database db = doc.Database;

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

		string sourceLayer = "DETAIL_" + pageToCopy;
		string targetLayer = "DETAIL_" + pageNumber;

		BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForWrite)
					as BlockTable;
		BlockTableRecord btr = tr.GetObject(bt[BlockTableRecord.ModelSpace],
			OpenMode.ForWrite) as BlockTableRecord;

		// Iterate BlockTableRecord.
		foreach (ObjectId id in btr) {

			// Entity for read.
			Entity ent = tr.GetObject(id, OpenMode.ForRead) as Entity;

			// Check cast is valid.
			if (ent != null) {

				// Check if entity is on source layer.
				if (ent.Layer == sourceLayer) {

					// Clone entity.
					Entity entClone = ent.Clone() as Entity;

					// Set clone to target layer.
					entClone.Layer = targetLayer;

					// Add clone to BlockTableRecord.
					btr.AppendEntity(entClone);
					tr.AddNewlyCreatedDBObject(entClone, true);
				}
			}
		}

		tr.Commit();
	}
}

 

0 Likes
Message 52 of 52

mgorecki
Collaborator
Collaborator

Hi Art,

Thanks, I'll check it out. 

 

Best regards,

Mark

0 Likes