Sort Objects by Selection Order

Hello. I’m still a beginner with Dynamo and had a question that came up at the office today: Is there a way to sort a list of selected objects by the order an object was selected? I understand how to filter an object and sort a list by id, name, etc. However, I have a condition (in the Python code) where I’m allowing the user to manually select objects desired. Is there a way to generate a list of the objects manually selected and keep the same order the objects were selected?

Thanks in advance for your assistance.

I think it’s the Rhythm or Springs package that has a node for just that.

2 Likes

Not trying to high-jack this thread as I work with aperez and he actually asked the question for me. I tried both the Rhythm and Springs packages and neither one does exactly as needed. They both do keep the selection order, however they utilize the PickObject method where the highlight disappears when the next object is selected. Ultimately, what I would like is to utilize the PickObjects method where the objects stay highlighted after selection. This is so the user knows which objects they have already selected to keep from selecting an object twice.

Thank you

As far as I know this is not possible. (Although I am hope I am wrong)

Yeah, that’s what I was afraid the response was going to be.
I appreciate all input!

Hello,
an alternative with the ‘ISelectionFilter’ class (interface UI) to avoid a new selection already made

import clr

clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *

clr.AddReference("RevitAPIUI")
from  Autodesk.Revit.UI import *

clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
doc = DocumentManager.Instance.CurrentDBDocument
uidoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument
sel1 = uidoc.Selection
obt1 = Selection.ObjectType.Element

clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)

class CustomISelectionFilter(Selection.ISelectionFilter):
	def __init__(self, lst_f):
		self.lst_f = lst_f
	def AllowElement(self, e):
		if e.Id not in self.lst_f:
			return True
		else:
			return False
	def AllowReference(self, ref, point):
		return True

out1 = []
lst_filter = []
flag = True

while flag:
	try:
		el1 = doc.GetElement(sel1.PickObject(obt1, CustomISelectionFilter(lst_filter), "Select a element, type escape to finish").ElementId)
		out1.append(el1.ToDSType(True))
		lst_filter.append(el1.Id)
	except :
		flag = False

OUT = out1
2 Likes

Thank you. Will give it a try.

Here is another example I found today https://pythoncvc.net/?p=116showing how to narrow it down to one category:

1 Like

Hi @c.poupin,

Is it possible to do the same for surface selection?

I have solution has include in package DynaMEP, you can try:
image

Hello @PiotrS you want return list of Faces or list of Elements ?

I would like to get list of Faces. I know how to change code below to select elements by its faces, but this is not the point :wink:

I want to pick those faces in my own order and get them into dynamo as Select Faces node.


@chuongmep it returns elements, not picked faces or am I wrong?

I Has add node for you, download package DynaMEP with version 1.2.8 or over to use it .

2 Likes

Hello @PiotrS

changing the selection mode is not enough you have to change the class that filters the selection

import clr
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *

clr.AddReference("RevitAPIUI")
from  Autodesk.Revit.UI import *

clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
doc = DocumentManager.Instance.CurrentDBDocument
uidoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument
sel1 = uidoc.Selection
obt1 = Selection.ObjectType.Face

clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)

class CustomISelectionFilter(Selection.ISelectionFilter):
	def __init__(self, lst_f):
		self.lst_f = lst_f
	def AllowElement(self, e):
		return True

	def AllowReference(self, ref, point):
		if ref.ConvertToStableRepresentation(doc) not in self.lst_f:
			return True
		else:
			return False		
out1 = []
lst_filter = []
flag = True

while flag:
	try:
		ref_1 = sel1.PickObject(obt1, CustomISelectionFilter(lst_filter), "Select a Face, type escape to finish")
		el1 = doc.GetElement(ref_1)
		face = el1.GetGeometryObjectFromReference(ref_1)
		out1.extend(face.ToProtoType())
		lst_filter.append(ref_1.ConvertToStableRepresentation(doc))
	except :
		flag = False

OUT = out1

also you can also use the node from @chuongmep :grinning:

4 Likes

@chuongmep , I tried Your node, but something goes wrong. After choosing one surface, node ends its work. It look like I am not able to pick more than one surface. Should I install some extra packages to try it? :slight_smile:

@c.poupin this python script works properly! Thank You for solution!

Hi PiotrS,
What version Revit and Dynamo you are using ?
At the moment don’t need intall extra packages

Revit 2018.3 and Dynamo 2.0.3 (.8810 - Dynamo Core and .8811 - Dynamo Revit)

you can Install the version 2.0.4
https://dyn-builds-data.s3-us-west-2.amazonaws.com/DynamoInstall2.0.4.exe

https://dynamobuilds.com/