Sorting a set of coordinate values (x,y,z) RRS feed

  • 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.



    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
                Return _x
            End Get
            Set(ByVal value As Single)
                _x = value
            End Set
        End Property

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

        Private _z As Single
        Public Property Z() As Single
                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 had not known about the ICompare method.

    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.



    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


                    If x1.Zcoordinate < y1.Zcoordinate Then

                        Return -1


                        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)


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

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




            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)


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



        End Sub


    End Class



    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,

    Thank you for your reply.

    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.

    Would you please clarify your above thread with an example?

    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))

    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 jinzai 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



    ' 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