# Sorting a set of coordinate values (x,y,z) • ### Question

• Hi all,

Any one aware of how to sort a set of point coordinates in the top to bottom, left to right fashion?

For example, I have a set of values like (3,5,10), (4,6,12), (4,6,1), (2,8,14).

. (2,8,14)

. (4,6,12)

. (3,5,10)

. (4,6,1)

I want this get sorted as (2,8,14), (4,6,12), (3,5,10), (4,6,1).

Any help in terms of advice or a code module much appreciated.

Thanks,

MNRaghu

Friday, December 23, 2005 7:03 AM

### All replies

• If you create a class to hold you points that implements IComparable(Of T), where T will be whatever your class is, then you can use Array.Sort to sort an array of such points.  The class would be something like this:

Public Class XyzPoint
Implements IComparable(Of XyzPoint)

Public Sub New(ByVal x As Single, ByVal y As Single, ByVal z As Single)
Me._x = x
Me._y = y
Me._z = z
End Sub

Public Overrides Function ToString() As String
Return "{" & String.Format("X={0}, Y={1}, Z={2}", Me.X, Me.Y, Me.Z) & "}"
End Function

Private _x As Single
Public Property X() As Single
Get
Return _x
End Get
Set(ByVal value As Single)
_x = value
End Set
End Property

Private _y As Single
Public Property Y() As Single
Get
Return _y
End Get
Set(ByVal value As Single)
_y = value
End Set
End Property

Private _z As Single
Public Property Z() As Single
Get
Return _z
End Get
Set(ByVal value As Single)
_z = value
End Set
End Property

Public Function CompareTo(ByVal other As XyzPoint) As Integer Implements System.IComparable(Of XyzPoint).CompareTo
Return New XyzPointComparer().Compare(Me, other)
End Function

Private Class XyzPointComparer
Implements IComparer(Of XyzPoint)

Public Function Compare(ByVal x As XyzPoint, ByVal y As XyzPoint) As Integer Implements System.Collections.Generic.IComparer(Of XyzPoint).Compare
If x.X.CompareTo(y.X) <> 0 Then Return x.X.CompareTo(y.X)
If x.Y.CompareTo(y.Y) <> 0 Then Return x.Y.CompareTo(y.Y)
If x.Z.CompareTo(y.Z) <> 0 Then Return x.Z.CompareTo(y.Z)
Return 0
End Function
End Class
End Class

If you do not like how the sorting is done, you can change the XyzPointComparer.Compare method to get what you want.
Saturday, December 24, 2005 1:55 PM
• Hi hgen_banks,

That seems to be a good answer.

I'll try the method and let you know again.

(Please let me know if you know any other method on the same issue.)

Thank you for the time spent for me. Appreciate your help.

MNRaghu

Sunday, December 25, 2005 5:52 AM
• HI

Just add a button and 2 Richtextboxes in your form. This code is generating random values for X, Y and Z coordinates and then sorts them according to Z coordinate in the set. If the coordinates are available or generated elsewhere then they can stored in a arrays then apply sort.

Option Strict On

Imports System.Collections

Public Class Form1

Public Structure MyXYZCoordinates ' Declare a structure of X, Y Coordinates

Dim XYcoordinates() As PointF ' X, Y coordinates Declared as a floating point

Dim Zcoordinate As Double

End Structure

Dim MyRand As New Random ' Declare random variable

Dim XYZCollection(5) As MyXYZCoordinates ' Declare an array of 10 XYZs

Dim New_TheXYZ As New MyXYZCoordinates ' Declare an Object reference to set it to an instance of an object.

Public Class ValueComparerClass

Implements IComparer(Of MyXYZCoordinates)

Public Function Compare(ByVal x1 As MyXYZCoordinates, ByVal y1 As MyXYZCoordinates) As Integer Implements System.Collections.Generic.IComparer(Of MyXYZCoordinates).Compare

If x1.Zcoordinate > y1.Zcoordinate Then

Return 1

Else

If x1.Zcoordinate < y1.Zcoordinate Then

Return -1

Else

Return 0

End If

End If

End Function

End Class

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

For XYZ = 0 To 5

RichTextBox1.AppendText(vbNewLine & "Set  " & XYZ + 1 & vbNewLine) ' Write set number to a text box

' Assigns dimensions to the array of X, Y points

ReDim New_TheXYZ.XYcoordinates(4) 'Handels and avoids Null Reference Exception

XYZCollection(XYZ) = New_TheXYZ ' Handels and avoids Null Reference Exception

For PointNumber = 0 To 4

' Assign random numbers from 0 to 10 for X coordinates

XYZCollection(XYZ).XYcoordinates(PointNumber).X = MyRand.Next(0, 11)

' Assign random numbers from 10 to 20 for Y coordinates

XYZCollection(XYZ).XYcoordinates(PointNumber).Y = MyRand.Next(11, 21)

' Print X, Y coordintes for each set in a text box.

RichTextBox1.AppendText(XYZCollection(XYZ).XYcoordinates(PointNumber).X & vbTab _

& XYZCollection(XYZ).XYcoordinates(PointNumber).Y & vbNewLine)

Next

XYZCollection(XYZ).Zcoordinate = MyRand.Next(100, 500)

RichTextBox1.AppendText(XYZCollection(XYZ).Zcoordinate & vbNewLine)

Next

Array.Sort(XYZCollection, New ValueComparerClass)

For XYZ = 0 To 5

RichTextBox2.AppendText(vbNewLine & "New Set  " & XYZ + 1 & vbNewLine)

For PointNumber = 0 To 4

RichTextBox2.AppendText(XYZCollection(XYZ).XYcoordinates(PointNumber).X & vbTab _

& XYZCollection(XYZ).XYcoordinates(PointNumber).Y & vbNewLine)

Next

RichTextBox2.AppendText(XYZCollection(XYZ).Zcoordinate & vbNewLine)

Next

End Sub

End Class

Cheers…

K Fendi - UK
Saturday, August 29, 2009 12:04 PM
• Note that the comparer needs to order pairs of coordinates according to the comparison rule.  You have not made this rule clear, but it appears to be based on distance from the (0,0,0) point.  It would be very inefficient to calculate this distance each time a pair of coordinates needs to be compared.

Your procedure should include an initial pass which calculates d for each coordinate.  This could be stored as a field in the coordinate structure, or it could be a parallel array which, once sorted, you use as an index into the coordinate array to enumerate that array in sequence.  The d value for each coordinate is then used for the comparison in the Icomparer.

Another advantage of this approach is that if the order needed to change then you can repeat the d calculation using a different origin, and then re-sort on the new d values.
Saturday, August 29, 2009 11:38 PM
• HI Acamar,

I agree with your helpful points. In addition, as I am aware of that PointF deals only with 2 dimensional planes (X and Y), the other dimension (Z) should be added as an array to the structure.

Public Structure MyXYZCoordinates ' Declare a structure of X, Y Coordinates

Dim XYcoordinates() As PointF ' X, Y coordinates Declared as a floating point

Dim Zcoordinate() As Double  ' Z coordinate Declaratio

End Structure

This means that each set in the structure have (x,y,z) coordinates. The comparison then should be made to a specific criteria such as distance between points (x,y) and this (as you mentioned) should be added as a filed in the structure.

Is it possible to store x,y,z coordinates as pointF in one variable in VB.Net so that:

xyzcoordinates.x = number

xyzcoordinates.y = number

xyzcoordinates.z = number

Kind Regards

K Fendi - UK
Monday, August 31, 2009 3:20 PM
• You might also consider using the Vector3 object from the DirectX SDK.  After installing the SDK, add a reference to Microsoft.DirectX to the project.  Then you can sort the Vector3 objects something like:

```Dim v1 As New Microsoft.DirectX.Vector3(3, 5, 10)
Dim v2 As New Microsoft.DirectX.Vector3(4, 6, 12)
Dim v3 As New Microsoft.DirectX.Vector3(4, 6, 1)
Dim v4 As New Microsoft.DirectX.Vector3(2, 8, 14)

Dim lst As New List(Of Microsoft.DirectX.Vector3)

Dim origin As New Microsoft.DirectX.Vector3(0, 0, 0)
lst.Sort(Function(vc1 As Microsoft.DirectX.Vector3, vc2 As Microsoft.DirectX.Vector3) _
Microsoft.DirectX.Vector3.Subtract(origin, vc2).Length.CompareTo( _
Microsoft.DirectX.Vector3.Subtract(origin, vc1).Length))

Console.WriteLine(lst(0))
Console.WriteLine(lst(1))
Console.WriteLine(lst(2))
Console.WriteLine(lst(3))
```

As previously noted, if you are going to resort frequently, you may need to make some enhancements to improve performance, but for the occasional sort this should work fine.

The main point here is that MS has already provided structures for handling points in 2D, 3D, and 4D space but they are located in the DirectX SDK and are not native to the framework.

Reed Kimble - "When you do things right, people won't be sure you've done anything at all"
• Proposed as answer by Monday, August 31, 2009 6:58 PM
Monday, August 31, 2009 4:41 PM
• Hi Reed Kimble

Is there a similar method in VB express edition 2008? Or and alternative new one in vb2008?

Kind Regards

K Fendi - UK
Tuesday, September 1, 2009 9:36 AM
• There is no difficulty in creating a structure with all the components discussed to date:

Public Structure MyXYZStruct' Define structure of X, Y, Z Coordinates

Dim Xcoordinate As Double  ' X coordinate structure element

Dim Ycoordinate As Double  ' Y coordinate structure element
Dim Zcoordinate As Double  ' Z coordinate structure element

Dim D as Double            ' Distance structure element

End

Structure

' Create a list of coordinates
Dim myXYZCoordinates As New List(Of MyXYZStruct)

However, the existing classes in DirectX (see below) are worth considering.
Tuesday, September 1, 2009 9:37 AM
• Hi K Fendi,

The sample code provided is in VB 2008.  Please be sure to install the DirectX SDK and add a reference to Microsoft.DirectX in the project.  The Vector3 object is defined in the DirecX API wrapper.

Hope that helps.
Reed Kimble - "When you do things right, people won't be sure you've done anything at all"
Tuesday, September 1, 2009 3:31 PM
• HI Reed

I got it.. THank you.
K Fendi - UK
Tuesday, September 1, 2009 4:56 PM