Sorting Points in 3D Space

Hello,

I am trying to sort a randomly ordered list of 3d grids of points. Assume a list of 7x7x7 = 343 points that need to be ordered in the manner shown in the below image.

How can I accomplish this?
image

Sort first by Y, then by X, last by Z. Consider rounding the coordinates first, otherwise the order might get messed up because of floating point precision.

Rather than sorting after the fact, I recommend you generate them in the desired order - one step instead of two.

In a code block:

List.Flatten(
	Point.ByCoordinates(				
		x<1>,
		y<2>,
		z<3>
	)
);
1 Like

@jacob.small @theshysnail ,

intresting … i am courous what will be the aim

KR

Andreas

Is the order number 51 in your picture meant to be 50?

1 Like

@pyXam

it is just a dummy with points … 0…10 points .

KR

Andreas

Yeah, it should be 50.

I have hundreds of storage boxes (cuboids with heights, lengths, and widths) in Revit for tagging in this fashion. The coordinates (location) are fixed, I need to just generate a sequence of numbers to tag them.

Oh so in reality it could be in any order, it just need to follow some sort of logic?

The sorting sequence will be the same.

Min Y, Min X, Column Z (ascending)
Min Y, Min X+1, Column Z (ascending)
Min Y, Min X+2, Column Z (ascending)

Min Y+1, Min X, Column Z (ascending)
Min Y+1, Min X+1, Column Z (ascending)
Min Y+1, Min X+2, Column Z (ascending)

Max X, Max Y, Max Z

List.GroupByKey and List.SortByKey can provide what you’re after, but you may need to concatenate the Y, X and Z values into a string first, or use three pairs of the nodes.

1 Like

A Python solution

import sys
import clr
import System
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

OUT = sorted(IN[0], key = lambda p : (p.Y, p.X, p.Z))

I take this opportunity to share solutions with data table (dataframe and.Net DataTable, which allows visualizing the data to check the output order)

  • dataframe solution (CPython3)
import sys
import clr
import System
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
import numpy as np
import pandas as pd

data = {}
data["Point"] = IN[0]
data["X"] = [x.X for x in IN[0]]
data["Y"] = [x.Y for x in IN[0]]
data["Z"] = [x.Z for x in IN[0]]

df = pd.DataFrame.from_dict(data)
df2 = df.sort_values(['Y', 'X', 'Z'])

OUT = df2["Point"].values
  • DataTable solution (IronPython)
import clr
import sys
import System
#
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
import Autodesk.DesignScript.Geometry as DS

#import net library
from System import Array
from System.Collections.Generic import List, IList, Dictionary

clr.AddReference('System.Data')
from System.Data import *
clr.AddReference('System.Data.DataSetExtensions')
clr.ImportExtensions(System.Data.DataTableExtensions)

clr.AddReference("System.Core")
clr.ImportExtensions(System.Linq)	

dt = DataTable("Points")
dt.Columns.Add('Point', DS.Point)
dt.Columns.Add('X', System.Double)
dt.Columns.Add('Y', System.Double)
dt.Columns.Add('Z', System.Double)
for pt in IN[0]:
	dt.Rows.Add(pt, pt.X , pt.Y, pt.Z)
 
dataView = dt.DefaultView
dataView.Sort = "Y, X, Z"
dt = dataView.ToTable()
                            
OUT = newDataTable.AsEnumerable().Select(lambda s : s["Point"]).ToArray[System.Object]()
3 Likes