Some code for handling coordinates and vectors in VB.Net. Coded in v2003. You need to import System.Math for the code to work.
Last updates: 21 April 2006
Current contents:
Coordinate Systems: Cartesian, Spherical Polar and Cylindrical Polar. Each can be defined with offsets and rotations relative to the global cartesian coordinate system.
Coordinate Transforms: From one local type to another, from any defined system to any other defined system, cartesian rotations (global and local).
The above code does the following:
-Creates a new cartesian coordinate system located at (10,10,0) with respect to the global, but with parallel axes.
-Generates three new coordinates within this system, (0,0,0), (1,0,0) and (0,1,0).
-Defines two new vectors within the system, one running along the x-axis and one along the y-axis.
-Defines a new vector by subtracting the y-axis vector from the x-axis vector. The new vector runs from (0,0,0) to (1,-1,0).
-Returns the endpoint of the new vector.
The picture illustrates how the offset and rotation properties are used: offsets are cartesian with respect to a global system centred at (0,0,0). The Theta rotation direction rotates the x axis onto the y axis, the Phi direction rotates the x axis onto the z axis and the Psi rotation angle rotates the y axis onto the z axis.
The same applies to the theta and phi coordinates in spherical and cylindrical polar coordinates.
There will be further additions to this code as necessary.
Dim mycartsystem As New CoordinateSystem.Cartesian(A, B, C, D, E, F, G)
A: The offset in the X direction
B: The offset in the Y direction
C: The offset in the Z direction
D: The rotation in the theta direction (about Z axis).
E: The rotation in the phi direction (about Y axis).
F: The rotation in the psi direction (about X axis)
G: The scale factor compared to the global. Scale factor of 2 means that 1 new unit = 2 global units.
All systems use these offsets, rotations and scales to define their position relative to the global cartesian system.
Create a coordinate:
Code:
Dim mycartcoord As New Coordinate.Cartesian(S, A, B, C)
S: The coordinate system in which to create the coordinate.
S=Cartesian / Spherical Polar / Cylindrical Polar
A: The X position / Radius R / Radius R
B: The Y position / Angle Theta / Angle Theta
C: The Z position / Angle Phi / Length Z
The values in A, B and C depend on the type of coordinate system used.
Create a vector:
Code:
Dim myvector1 As New Vector.Cartesian
myvector1.StartPoint = mycartcoordorigin
myvector1.EndPoint = mycartcoord
Cartesian vectors have a startpoint and endpoint, which are both coordinates. They also have X1, Y1, Z1 properties which are the X, Y and Z values of Startpoint, and X2, Y2, Z2 properties which are the X, Y and Z values of Endpoint.
In addition, vectors have a length property, which is calculated whenever the start or end points change. If the Length property is set directly, then the startpoint remains in place and the endpoint is recalculated.
Vectors can be located in a coordinate system.
Angle operations:
Code:
myangle = Operations.Angles.Degrees(myangle) 'Radians to degrees
myangle = Operations.Angles.Radians(myangle) 'Degrees to radians
Transforms a spherical polar coordinate to the equivalent in local cartesians, i.e. the cartesian system with the same origin, rotation and scale with respect to the global cartesian system.
Equivalent functions transform a coordinate between local spherical, cylindrical and cartesian coordinate systems.
Transforms the coordinate mycartcoord in a cartesian coordinate system to the new coordinate mysphcoord in the spherical polar system mysphsys. Overloaded to accept coordinates and systems in Cartesian, Spherical polar and Cylindrical Polar styles.
Vector operations:
Code:
C = Operations.VectorOps.Add(A, B)
Returns the resultant vector C from the vector sum (A + B)
Code:
C = Operations.VectorOps.Subtract(A, B)
Returns the resultant vector C from the vector subtraction (A - B)
Code:
D = Operations.VectorOps.DotProduct(A, B)
Returns the scalar D which is the dot product of two vectors (A.B)
Code:
C = Operations.VectorOps.CrossProduct(A, B)
Returns the vector C which is the cross product of two vectors (AxB)
Code:
C = Operations.VectorOps.TranslateStart(A, mycartcoord)
Translates the vector A such that the new start point is at the coordinate mycartcoord. A similar function TranslateEnd translates the endpoint to the coordinate mycartcoord.
Solids:
Code:
Dim mysolid As New Solids.Sphere(A, B, C, D)
Generates a new set of coordinates on a spherical volume. The volume is centred on the origin of coordinate system A with radius B. There are C points on each of D layers. It is also possible to generate ellipsoids, cuboids and cylinders.
If circ.Theta >= Operations.Angles.Radians(359) Then circ.R = circ.R + 10
If circ.R > 285 / 3 Then Timer1.Enabled = False
End Sub
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.Width = 400
Me.Height = 400
Timer1.Interval = 100
Timer1.Enabled = True
End Sub
As before, we are looking down from the z axis at the xy plane. This code sets up a spherical polar coordinate system called circsystem located at (200,200). Within that, a spherical polar coordinate called circ is defined with radius 10 and no angle (i.e. along the x axis). On each timer tick, the circle is drawn at the current circ coordinate, and then the theta parameter of the coordinate is incremented by 5 degrees (using the Angles.Radians operation to convert into radians). When the angle is greater than 359 degrees, the radius is incremented by 10. The timer is stopped when the radius gets too big.
Within the drawcircle sub, a cartesian coordinate is defined and used to transform the spherical polar coordinate into the local cartesian coordinates, i.e. into coordinates that can be used for drawing on a form. The circle is then drawn. The colour of the pen is set to change with the radius, so that it blends from red to green.
You could also try the following code:
VB Code:
Friend circsystem As New CoordinateSystem.SphericalPolar(200, 200, 0, 0, Operations.Angles.Radians(45))
Friend circ As New Coordinate.SphericalPolar(circsystem, 10, 0, 0)
Friend rotcircsystem As New CoordinateSystem.SphericalPolar(200, 200)
Friend Sub drawcircle()
Dim graphics As System.Drawing.Graphics = Me.CreateGraphics()
If circ.Theta >= Operations.Angles.Radians(359) Then circ.R = circ.R + 10
If circ.R > 285 / 3 Then Timer1.Enabled = False
End Sub
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.Width = 400
Me.Height = 400
Timer1.Enabled = True
End Sub
Here, the coordinate system circsystem is rotated by 45 degrees about the y axis (i.e. phi = 45 degrees, see picture in previous post), so the right-hand side of the system is tilted towards you and the left-hand side away from you. We are now no longer looking from the z axis of circsystem, so we need to define another coordinate system which corresponds to our viewpoint, called rotcircsystem. We are looking from the z axis of rotcircsystem, and the coordinate newcirccoord within it is used to transform from the tilted coordinate system circsystem. The effect is to take the previous example and tilt it by 45 degrees, pulling the RHS towards you and the LHS away from you.
Update: Added in a Psi rotation about the x axis. You can now rotate about all three cartesian axes.
3) Plot a rotating cube
Add a picturebox called Picturebox1 and a timer called Timer1 to your form and then add the following code:
VB Code:
Friend cartsystem As New CoordinateSystem.Cartesian(200, 200, 0, Operations.Angles.Radians(30), Operations.Angles.Radians(0), Operations.Angles.Radians(0))
Friend cartx As New Coordinate.Cartesian(cartsystem, 100, 0, 0)
Friend carty As New Coordinate.Cartesian(cartsystem, 0, 100, 0)
Friend cartz As New Coordinate.Cartesian(cartsystem, 0, 0, 100)
Friend cartxy As New Coordinate.Cartesian(cartsystem, 100, 100, 0)
Friend cartxz As New Coordinate.Cartesian(cartsystem, 100, 0, 100)
Friend cartyz As New Coordinate.Cartesian(cartsystem, 0, 100, 100)
Friend cartxyz As New Coordinate.Cartesian(cartsystem, 100, 100, 100)
Friend myview As New CoordinateSystem.Cartesian(200, 200)
Friend Sub drawcube()
Dim graphics As System.Drawing.Graphics = PictureBox1.CreateGraphics
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.Width = 600
Me.Height = 600
PictureBox1.Left = 0
PictureBox1.Top = 0
PictureBox1.Width = 600
PictureBox1.Height = 600
Timer1.Interval = 100
Timer1.Enabled = True
End Sub
The angles specified in Cartsystem denote the starting orientation, whilst the 7 coordinates denote the 7 vertices of the cube. The eighth, at (0,0,0) is implied and left as the offest of the coordinate system. Different coloured pens are used to colour the edges and the timer is used to rotate the angle of the coordinate system in the theta, phi and psi directions by 1 degree (converted to radians).
To make it drift as well, put the following into the timer in addition:
VB Code:
cartsystem.XOffset = cartsystem.XOffset + 1
cartsystem.YOffset = cartsystem.YOffset + 1
myview.XOffset = myview.XOffset + 1
myview.YOffset = myview.YOffset + 1
4) Simple graphing
You will need a picturebox called Picturebox1 and a timer called Timer1.
Paste the following code:
VB Code:
Friend cartsystem As New CoordinateSystem.Cartesian(200, 400, 0, Operations.Angles.Radians(0), Operations.Angles.Radians(45), Operations.Angles.Radians(45), 50)
Friend myview As New CoordinateSystem.Cartesian(200, 200)
Friend Sub drawgraph()
Dim i As Integer
Dim plotcoord As New Coordinate.Cartesian(cartsystem, 0, 0, 0)
Dim graphics As System.Drawing.Graphics = PictureBox1.CreateGraphics
Dim mypen As New System.Drawing.Pen(System.Drawing.Color.Green)
Dim axispen As New System.Drawing.Pen(System.Drawing.Color.Black)
Dim myview As New CoordinateSystem.Cartesian(cartsystem.XOffset, cartsystem.YOffset)
Dim mycoord As New Coordinate.Cartesian(myview, 0, 0, 0)
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.Width = 680
Me.Height = 600
PictureBox1.Left = 80
PictureBox1.Top = 0
PictureBox1.Width = 600
PictureBox1.Height = 600
Timer1.Interval = 100
Timer1.Enabled = True
End Sub
Here, a function called y(x) is used to calculate x^2 for each value of x within the For loop in the Drawgraph routine. The rectangle is drawn at the system offset position + the point offset position and then adjusted to centre the circle before the ellipse is actually drawn.
As usual, the cartesian system cartsystem is used as the graph coordinate system whilst myview transforms it to the screen coordinate system. Cartsystem is tilted so as to be easier to view and rotated using the timer. Axes are drawn in black and points in green.
where newcoord and oldcoord are cartesian coordinates, angle is double in radians and Theta indicates to rotate about the local Z axis (by angle radians). There are also Phi and Psi operations to rotate about the y and z axes respectively.
5) Rotate a cube about its local axes
Add a picturebox called Picturebox1 and a timer called Timer1 to your form and then add the following code:
VB Code:
Friend cartsystem As New CoordinateSystem.Cartesian(250, 250, 0, Operations.Angles.Radians(0), Operations.Angles.Radians(45), Operations.Angles.Radians(45), 1)
Friend cartorig As New Coordinate.Cartesian(cartsystem, -50, -50, -50)
Friend cartx As New Coordinate.Cartesian(cartsystem, 50, -50, -50)
Friend carty As New Coordinate.Cartesian(cartsystem, -50, 50, -50)
Friend cartz As New Coordinate.Cartesian(cartsystem, -50, -50, 50)
Friend cartxy As New Coordinate.Cartesian(cartsystem, 50, 50, -50)
Friend cartxz As New Coordinate.Cartesian(cartsystem, 50, -50, 50)
Friend cartyz As New Coordinate.Cartesian(cartsystem, -50, 50, 50)
Friend cartxyz As New Coordinate.Cartesian(cartsystem, 50, 50, 50)
Friend myview As New CoordinateSystem.Cartesian(250, 250)
Friend Sub drawcube()
Dim graphics As System.Drawing.Graphics = PictureBox1.CreateGraphics
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.Width = 680
Me.Height = 600
PictureBox1.Left = 80
PictureBox1.Top = 0
PictureBox1.Width = 600
PictureBox1.Height = 600
Timer1.Interval = 20
Timer1.Enabled = True
End Sub
Here, the code in the timer is used to rotate each of the corner points of the cube in the Psi direction (about local x axis) by 2 degrees before plotting it. Note that the positions of the axes do not change and the cube is rotating about them.
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.Width = 680
Me.Height = 600
PictureBox1.Left = 80
PictureBox1.Top = 0
PictureBox1.Width = 600
PictureBox1.Height = 600
Timer1.Interval = 100
Timer1.Enabled = True
End Sub
The solids are generated within their own coordinate systems (circsystem, cylsystem or cubsystem) and rotated about the z axis with the timer.
drawcircsolid generates the wireframe mesh for the sphere, ellipsoid and cylinder - change the commented lines to choose a different solid. drawcuboid generates the cuboid. Choose which by changing the comment in the Timer code.
The parameters of the solids can be changed so that, for example, the cuboid routine generates a cube or the ellipsoid routine generates a sphere.
Note that when generating cylinders, the number of layers includes any circles on the ends of the cylinder - the number of layers in between are then calculated from what is left.
Hi Zaza, sorry for dredging up such an old post. Please could you tell me if the classes you have outlined here can be used for transforming cartesian points from the world coordinate system to a user coordinate system defined by an origin, positive x point and positive y point? I can see transforms between different coordinate systems, but nothing as above.
At the moment I am using methods built into a CAD API I am using, but I would like to do the transforms without having to refer to 3rd party objects.
These are just general coordinate transforms, so they will work between any two coordinate systems howsoever defined.
If you were to use them to define both your "world" system and your "user" system according to whatever the relational conditions are, then the methods and functions here will allow you to transform between them at will.
Hi Zaza, I have converted the classes to C# and all seems to be working. The only problem I have had so far is that most of the CAD packages I have worked with define coordinate systems by specifying 3 points; an origin point, a positive point on the X axis, and a positive point on the Y axis.
Your method for specifying a coordinate system is with x, y, and z offsets and with rotations around the 3 axes. I can get the offsets OK, these should just be the coordinates of the origin point, but I am struggling with calculating the angles from the other 2 points.
I have tried this method, which works the way I thought it should for rotations around the z axis, but I think I'm doing something silly that causes it to misbehave for rotations in the other axes: