Autocad does not have a 3D arc command and its kind of wild how hard it is to draw an arc on a sphere. I think we can do it, but there is a lot of theory involved, which is good because its fun and what else were you going to do? Googling the problem, the best solution I saw (which i won’t use here) was “ProjectGeometry” where a line drawn from point to point on the sphere is projected onto the solid sphere object and converted to an arc. I did not spend a lot of time looking for it, but I am not sure if that method is available in activeX. Its not an object type. Its a command, a written program in autocad, so its a manual technique. Although possibly you could use sendcommand or something similar.
To draw an arc on a sphere – two endpoints, center and radius will be the givens. Two vectors from 0,0,0 to the endpoints are drawn. The dot product, also called the scalar product of two vectors, has all the theory we need to construct a new ucs in the plane of the vectors and the arc we want to draw. Its a math topic in a beginning vectors class. The dot product is a calculation that projects a perpendicular from one vector to the other. The point that it touches becomes the origin of the new ucs. The new x-axis is defined by the endpoint of the vector, and the new y-axis is defined by the projecting vector endpoint. The 3 points must form a right angle, which they do. The dot product also gives us the included angle between the vectors, just from the endpoint coordinates. very nice.
There is no way to draw an arc that is not parallel to the current ucs, so you have to change the ucs. However all the other data that goes into creating an arc stays tied to the World ucs, as far as drawing in activeX is concerned. If you are drawing manually, autocad accomodates your desire to draw in the new ucs. 0,0,0 typed in at the command line is interpreted to be the new ucs origin. Activex generally ignores the ucs, except as it defines the drawing plane.
Draw an arc with any method then look at the arc in the properties window to see what data is read/write and what is grayed out. You can edit the center xyz coordinates, the radius, the start and end angle. Thats all. Those are the exact same prompts the activex addarc requires. Moving the center moves it parallel to its plane of creation. If the other data are changed, the shape of the curve is changed and new endpoints are calculated by autocad, but it stays parallel to the plane it was made in.
Startangle is a hard problem. With the dot product, we can calculate the included angle from the endpoints. We know the center and the radius. The startangle for the arc is not the angle from the current ucs. It is not the angle projected onto the world ucs. With 2D vectors, there is only one reference angle, the angle from the vector to the positive X axis. In the 2D plane autocad measures angles from the positive x-axis. The angle of a 3D vector is defined by the angle from the vector directly to each positive axis. The angle to the X-axis is called the Alpha angle. In the tilted ucs I did not see what the logic of startangle was. I drew an arc with startangle zero, and the arc touched down on the world x-axis. The startangle is the vector direction angle Alpha from the new x-axis directly to the world x-axis. But it is not that simple either. My vectors were 5,5,5 and -5,5,5. They were symmetrical across the z-axis, which made an alpha projection hit the x-axis. If the ucs has another twist, the alpha angle will extend to where it breaks the xy plane apparently.
I need to find the intersection of the ucs with the world xy plane. The only way i know how to do it right now is to draw an arc with startangle 0 and see where it starts. Pretty sure its a solvable problem.
(actually have ny and la backwards labeled. my latitude longtitude converter is not handling east west correctly, the arclength came out correct)
Sub A_scalar_dot_B(x1 As Double, y1 As Double, z1 As Double, x2 As Double, y2 As Double, z2 As Double) Dim ptA() As Double Dim ptB() As Double Dim A_dot_B As Double Dim len_A As Double Dim len_B As Double Dim cos_theta As Double Dim theta As Double Dim theta_deg As Double Dim A_unit_vector() As Double Dim A_unit_x As Double Dim A_unit_y As Double Dim A_unit_z As Double Dim B_unit_vector() As Double Dim B_unit_x As Double Dim B_unit_y As Double Dim B_unit_z As Double Dim scalar_B_on_A As Double Dim scalar_A_on_B As Double Dim pt_scalar_B_on_A() As Double ptA = pt(x1, y1, z1) ptB = pt(x2, y2, z2) A_dot_B = x1 * x2 + y1 * y2 + z1 * z2 len_A = (x1 ^ 2 + y1 ^ 2 + z1 ^ 2) ^ (1 / 2) len_B = (x2 ^ 2 + y2 ^ 2 + z2 ^ 2) ^ (1 / 2) cos_theta = A_dot_B / (len_A * len_B) theta = WorksheetFunction.Acos(cos_theta) theta_deg = rad2deg(theta) A_unit_x = x1 / len_A A_unit_y = y1 / len_A A_unit_z = z1 / len_A B_unit_x = x2 / len_B B_unit_y = y2 / len_B B_unit_z = z2 / len_B scalar_B_on_A = len_B * cos_theta scalar_A_on_B = len_A * cos_theta pt_scalar_B_on_A = pt(A_unit_x * scalar_B_on_A, A_unit_y * scalar_B_on_A, A_unit_z * scalar_B_on_A) ucs pt_scalar_B_on_A, ptA, ptB, "wow" Debug.Print theta_deg public_theta_deg = theta_deg End Sub
Sub testconv() Call Connect_Acad pt0 = pt(0, 0, 0) set_ucs 0, 0, 0, 1, 0, 0, 0, 1, 0, "world" pt1 = conv(40.713, 74.006, 3963) 'NEW YORK pt2 = conv(34.052, 118.244, 3963) 'LOS ANGELES 'CONV IS PRELIMINARY line1 pt0, pt1 line1 pt0, pt2 Call A_scalar_dot_B(pt1(0), pt1(1), pt1(2), pt2(0), pt2(1), pt2(2)) Dim r As Double r = 3963 'RADIUS IN MILES Dim alpha As Double alpha = 85.727 ' alpha = 0 'try 0, measure and input value arc1 pt0, r, alpha, alpha + public_theta_deg Debug.Print pt1(0) Debug.Print pt1(1) Debug.Print pt1(2) Debug.Print pt2(0) Debug.Print pt2(1) Debug.Print pt2(2) acadApp.Update End Sub