AutoCAD Plant 3D Forum
Welcome to Autodesk’s AutoCAD Plant 3D Forums. Share your knowledge, ask questions, and explore popular AutoCAD Plant 3D topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Select and Zoom Nozzle using C#

4 REPLIES 4
SOLVED
Reply
Message 1 of 5
sambhaji_burungale
268 Views, 4 Replies

Select and Zoom Nozzle using C#

 

Hello Everyone,

 

I want to implement select and zoom feature for Plant3d components using their PnPID.

 

For select and zoom, I am using SelectObjects and ZoomObjects methods of Autodesk.AutoCAD.Internal.Utils as shown below.

 

 

 

List<ObjectId> objectsToBeSelected = new List<ObjectId>();

var pnPObjIds = dataLinksManager.FindAcPpObjectIds(nozzlePnpId)?.ToList()

if (pnPObjIds?.Count > 1)
{
    var target = dataLinksManager.MakeAcDbObjectId(pnPObjIds.First());
    
    if (target != ObjectId.Null)
    {
        objectsToBeSelected.Add(target);

        Autodesk.AutoCAD.Internal.Utils.SelectObjects(objectsToBeSelected.ToArray());
        Autodesk.AutoCAD.Internal.Utils.ZoomObjects(false);
    }
}

 

 

 

It works fine for piping components and equipment. However, the SelectObjects method needs objectIds as input. And for Nozzles, the MakeAcDbObjectId method always returns ObjectID of owner equipment.

 

I tried below approaches to get the objecdID of nozzle. But it did not work. It seems SubParts does not have object id.

 

 

 

var pnPObjIds = dataLinksManager.FindAcPpObjectIds(nozzlePnpId)?.ToList();

var target = dataLinksManager.MakeAcDbObjectId(pnPObjIds.First());

var db = Application.DocumentManager.MdiActiveDocument.Database;

var componentDBObject = db.TransactionManager.StartOpenCloseTransaction()?.GetObject(target , OpenMode.ForRead);

if (componentDBObject is Equipment equipment)
{
    var nozzles = equipment.AllSubParts;

    foreach (NozzleSubPart nozzle in nozzles)
    {
        if (nozzlePnpId.Equals(nozzle.PartSizeProperties.PartId))
        {
            var nozzletarget = nozzle.Id;   // This is always Null. (ObjectId.Null)

            var acPpObjId = dataLinksManager.MakeAcPpObjectId(target, nozzle.Index);
            target = dataLinksManager.MakeAcDbObjectId(acPpObjId); // This still gives owner equipment ObjectID.

            if (target != ObjectId.Null)
            {
            	objectsToBeSelected.Add(target);

            	Autodesk.AutoCAD.Internal.Utils.SelectObjects(objectsToBeSelected.ToArray());
            	Autodesk.AutoCAD.Internal.Utils.ZoomObjects(false);

            	break;
            }
        }
    }
}

 

 

 

 

 

I was able to highlight the nozzle using below code. But still no luck for actual selection (that happens with control key + mouse click) and zoom. Any guidance with this issue will be greatly appreciated.

 

 

 

var pnPObjIds = dataLinksManager.FindAcPpObjectIds(nozzlePnpId)?.ToList();

var target = dataLinksManager.MakeAcDbObjectId(pnPObjIds.First());

var db = Application.DocumentManager.MdiActiveDocument.Database;

var componentDBObject = db.TransactionManager.StartOpenCloseTransaction()?.GetObject(target , OpenMode.ForRead);

if (componentDBObject is Equipment equipment)
{
    var nozzles = equipment.AllSubParts;

    foreach (NozzleSubPart nozzle in nozzles)
    {
        if (nozzlePnpId.Equals(nozzle.PartSizeProperties.PartId))
        {
            using (Transaction tr = doc.Database.TransactionManager.StartTransaction())
			{
				Entity entity = tr.GetObject(target, OpenMode.ForRead) as Entity;

				ObjectId[] entId = new ObjectId[] { entity.ObjectId };
				SubentityId subentity = new SubentityId(SubentityType.Null, new IntPtr(nozzle.Index));
				
				FullSubentityPath path = new FullSubentityPath(entId, subentity);

				entity.Highlight(path, true);

				PnPRow[] subpartrows = dataLinksManager.GetPnPDatabase().Tables["EngineeringItems"].Select($"PnPID={nozzlePnpId}");

				if (subpartrows.Length != 0)
				{
					 // Implement Zoom with subpartrows[0]["Position X"],subpartrows[0]["Position Y"],subpartrows[0]["Position Z"]
				}
				
				tr.Commit();
				
				break;
			}
        }
    }
}

 

 

 

 

Thank You!

Sambhaji Burungale

 

 

 

4 REPLIES 4
Message 2 of 5
Message 3 of 5

Thank you Jason!

 

I tested Zoom with code provided in link. Mostly, it worked. However, sometime zoom just does not happen if I have zoomed out to see entire drawing. As a workaround, I tried following and it worked mostly.

 

1. Select Equipment

2. Zoom Equipment

3. Clear Equipment Selection

4. Zoom Nozzle

 

 

var pnPObjIds = dataLinksManager.FindAcPpObjectIds(nozzlePnpId)?.ToList();

var target = dataLinksManager.MakeAcDbObjectId(pnPObjIds.First());

// Select and Zoom Equipment
objectsToBeSelected.Add(target);
Autodesk.AutoCAD.Internal.Utils.SelectObjects(objectsToBeSelected.ToArray());
Autodesk.AutoCAD.Internal.Utils.ZoomObjects(true);

// Clear Equipment selection so that the nozzle selection will be visible.
doc.Editor.SetImpliedSelection(new ObjectId[0]);
objectsToBeSelected.Clear();

// Zoom Nozzle
var nozzlePnPRow = pnpDb.Tables["EngineeringItems"].Select($"PnPID={nozzlePnpId}").FirstOrDefault();

if (nozzlePnPRow != null)
{
	ZoomToPoint(new Point3d(Convert.ToDouble(nozzlePnPRow["Position X"]),
									  Convert.ToDouble(nozzlePnPRow["Position Y"]),
									  Convert.ToDouble(nozzlePnPRow["Position Z"])));
}


public static void ZoomToPoint(Point3d pCenter)
{
	var ed = Application.DocumentManager.MdiActiveDocument.Editor;
	
	using (var view = ed.GetCurrentView())
	{
		var UCS2DCS =
			(Matrix3d.Rotation(-view.ViewTwist, view.ViewDirection, view.Target) *
			Matrix3d.Displacement(view.Target - Point3d.Origin) *
			Matrix3d.PlaneToWorld(view.ViewDirection)).Inverse() *
			ed.CurrentUserCoordinateSystem;
		var center = pCenter.TransformBy(UCS2DCS);
		view.CenterPoint = new Point2d(center.X, center.Y);
		ed.SetCurrentView(view);
	}
}

 

 

Do you have any suggestions for selecting nozzle?

 

In drawing, we use control key and mouse click to select nozzle. Can we achieve this using SDK?

 

Thank You,

Sambhaji Burungale

Message 4 of 5


@sambhaji_burungale wrote:

In drawing, we use control key and mouse click to select nozzle. Can we achieve this using SDK?


I'm not aware of any method for this.

Message 5 of 5

Thank you @jabowabo, for the assistance. 

 

Finally, I have found solution!! The trick was to use  SetImpliedSelection(SelectionSet selectionSet) method of editor. Here is the complete solution..

 

 

public void SelectNozzle(int nozzlePnpId)
{
	var pnPObjIds = dataLinksManager.FindAcPpObjectIds(nozzlePnpId)?.ToList();
	
	if(pnPObjIds?.Count == 0)
		return;

	var target = dataLinksManager.MakeAcDbObjectId(pnPObjIds.First());

	if(target == ObjectId.Null)
		return;
		
	if (Runtime.IsPnP3dEquipment(target))
	{
		Document doc = Application.DocumentManager.MdiActiveDocument;

		var equipment = doc.Database.TransactionManager.StartOpenCloseTransaction()?.GetObject(target , OpenMode.ForRead) as Equipment;

		var nozzles = equipment.AllSubParts;

		foreach (NozzleSubPart nozzle in nozzles)
		{
			if (nozzlePnpId.Equals(nozzle.PartSizeProperties.PartId))
			{
				SelectSubentity(target, nozzleEntity.Index, SubentityType.Face);
				break;
			}
		}
	}
}

public void SelectSubentity(ObjectId target, int subEntityIndex, SubentityType subentityType)
{
    Document doc = Application.DocumentManager.MdiActiveDocument;

    using (Transaction tr = doc.Database.TransactionManager.StartTransaction())
	{
		Entity entity = tr.GetObject(target, OpenMode.ForRead) as Entity;

		ObjectId[] entId = new ObjectId[] { entity.ObjectId };

		SubentityId subentity = new SubentityId(subentityType, new IntPtr(subEntityIndex));

		FullSubentityPath path = new FullSubentityPath(entId, subentity);

		var gsMarkers = entity.GetGraphicsMarkersAtSubentityPathIntPtr(path);

		if (gsMarkers.Count > 0)
		{
			var selectedSubObjects = new SelectedSubObject[]
			{
				new SelectedSubObject(path, SelectionMethod.NonGraphical, gsMarkers[0])
			};

			var selectedObjects = new List<SelectedObject>
			{
				new SelectedObject(target, selectedSubObjects)
			};

			var subEntitySelectionSet = new SubEntitySelectionSet(selectedObjects);

			doc.Editor.SetImpliedSelection(subEntitySelectionSet);
			
			Autodesk.AutoCAD.Internal.Utils.ZoomObjects(true);
		}

		tr.Commit();
	}
}

// I was not able to use SelectionSetDelayMarshalled class present in SDK
// as it could not be instantiated. So, I had to write my own.
public class SubEntitySelectionSet : SelectionSet
{
    List<SelectedObject> selectedObjects = new List<SelectedObject>();

    public SubEntitySelectionSet(IEnumerable<SelectedObject> selections)
	{
        selectedObjects.AddRange(selections);
    }

    public override SelectedObject this[int index] => selectedObjects[index];

	public override int Count => selectedObjects.Count;

	public override IEnumerator GetEnumerator()
	{
        return selectedObjects.GetEnumerator();
	}

	public override ObjectId[] GetObjectIds()
	{
        return selectedObjects.Select(s => s.ObjectId).ToArray();
    }
}

 

 

 

Thanks and Regards,

Sambhaji Burungale

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

Post to forums  

Technology Administrators


Autodesk Design & Make Report