I have line and circle model (I know the equation that is formed by using data). I would like to find tangent points or equation of yellow circle (radius is determined by me) which tangent with my line and circle.
At the beginning I tried to solve mutual equation separately line and yellow circle and circle and yellow circle reduce to 3 equation to 2 equation but I couldn't find a solution maybe calculation error.
Is there any more clear way or opinion to find these points by python?
For example:
Circle-1: (x-8,98)^2 + (y-42,53)^2 = 6,4^2
Line-1: y=22,904x-115,9707
Tangent Circle:(x-a)^2 + (y-b)^2 = 14^2
Tangent points (Founded in AutoCAD):
X1=6,2028
Y1=26,0978
X2=12,4953
Y2=37,1832
Your problem has multiple solutions.
You have 6 unknowns, so the simplest way to solve the problem (not necessarily the fastest) is to craft 6 equations using the constraints defined. After that, you can use a symbolic Math engine like Sympy to solve the system of equations.
Let's start by defining the equations.
We know that the line-2 between P1 and the center of the second circle (its center is hereafter noted as (x_a2, ya_2)) is perpendicular to the line 1 whose slope is equal to a . So the slope of the perpendicular line-2 is equal to -1/a. And since A2 and P1 are on line-2, we have the following
P1 is on circle-2, so
P1 is on line-1, so
We know that the Euclidean distance between the center of the two circles is equal to r1 + r2, so
P2 is on circle-1,
P2 is on circle-2,
We have finally the 6 equations, so we can use Sympy to solve the system of equations.
I recommend running the following code on a Jupyter notebook
#%%
#imports
import sympy as sp
from sympy import Eq
from sympy.physics.mechanics import dynamicsymbols
from sympy.physics.vector import init_vprinting
init_vprinting(use_latex='mathjax', pretty_print=False)
#%%
#Unknows and variables definition
x_a1, y_a1, r_1, r_2, a, b = 8.98, 42.53, 6.4, 14, 22.904, -115.97
x_a2, y_a2, x_p1, y_p1, x_p2, y_p2 = dynamicsymbols('x_a2 y_a2 x_p1 y_p1 x_p2 y_p2')
#%%
#equations definition
eq1 = Eq(y_p1-y_a2,(1/a)*(x_a2-x_p1))
eq2 = Eq((x_p1-x_a2)**2+(y_p1-y_a2)**2,r_2**2)
eq3 = Eq(y_p1, a * x_p1 + b)
eq4 = Eq((x_a2-x_a1)**2+(y_a2-y_a1)**2,(r_1 + r_2)**2)
eq5 = Eq((x_p2-x_a1)**2+(y_p2-y_a1)**2,r_1**2)
eq6 = Eq((x_p2-x_a2)**2+(y_p2-y_a2)**2,r_2**2)
eq4 = sp.expand(eq4)
eq5 = sp.expand(eq5)
#%%
#solve the system
sp.solve((eq1,eq2,eq3,eq4,eq5,eq6), (x_a2, y_a2, x_p1, y_p1, x_p2, y_p2))
Here are the solutions (in this order: [x_a2, y_a2, x_p1, y_p1, x_p2, y_p2]) I got,
[(−7.61137900888098, 30.6604531432888, 6.37529636566885, 30.0497879592794, 3.77486148740989, 38.8062205939729),
(−6.51375646949495, 55.8003997853864, 7.47291890505488, 55.1897346013771, 4.11921365662903, 46.6932626777683),
(20.1893606892033, 25.4856392628135, 6.20268531465346, 26.0963044468229, 12.496662177005, 37.1827495726474),
(21.6322053306201, 58.5325529298243, 7.64552995607028, 59.1432181138336, 12.9493193194102, 47.5504087622978)]
The third solution is the one given by AutoCAD (and the one represented in your figure)
Related
I want to solve this problem using sympy but I am not sure how. I know how to minimize the surface area of a cuboid using calculus but not using python.
Use sympy to minimize the surface area of a square cuboid made up of top and bottom squares and four rectangular sides meeting at right angles. Let s be the length of the square's side and h be the height.
Let s be the length of the square's side and h be the height. The square cuboid's surface area is A = 2x^2+4hs since 2s^2 is the combined area of its top and bottom squares, and 4hs is the combined area of its sides. Its volume is given by V=s^2h.
The problem is to use sympy to compute the exact value of s that minimizes the square cuboid's surface area A subject to the constraint V=1. Is there a common name for the area-minimizing solid you come up with?
Sympy doesn't seem to have a function for symbolic minimization. One could
Here is a possible approach:
from sympy import symbols, Eq, solve, lambdify
h, s = symbols('h s', real=True, positive=True)
# formula for the area
A = s * s + 4 * h * s
# equation for the volume which should be 1
volume = Eq(s * s * h, 1)
# h_given_s = solve(volume, h)[0] # h_given_s = s**(-2)
# using the volume equation, express h as a function of s
# and substitute that solution into A
A_s = A.subs(h, solve(volume, h)[0]) # A = s**2 + 4/s
# find the zeros of the first derivative
ans = solve(A_s.diff(s))[0]
print(f'answer: {ans} (={ans.evalf()})')
answer: 2**(1/3) (=1.25992104989487)
Another approach would involve scipy's numeric minimization:
from scipy.optimize import minimize as scipy_min
A_np = lambdify(s, A_s)
scipy_min(A_np, 1)
Result: 1.25992129
I'm trying to fit a line segment to a set of points but I have trouble finding an algorithm for it. I have a 2D line segment L and a set of 2D points C. L can be represented in any suitable way (I don't care), like support and definition vector, two points, a linear equation with left and right bound, ... The only important thing is that the line has a beginning and an end, so it's not infinite.
I want to fit L in C, so that the sum of all distances of c to L (where c is a point in C) is minimized. This is a least squares problem but I (think) cannot use polynmoial fitting, because L is only a segment. My mathematical knowledge in that area is a bit lacking so any hints on further reading would be appreciated aswell.
Here is an illustration of my problem:
The orange line should be fitted to the blue points so that the sum of squares of distances of each point to the line is minimal. I don't mind if the solution is in a different language or not code at all, as long as I can extract an algorithm from it.
Since this is more of a mathematical question I'm not sure if it's ok for SO or should be moved to cross validated or math exchange.
This solution is relatively similar to one already posted here, but I think is slightly more efficient, elegant and understandable, which is why I posted it despite the similarity.
As was already written, the min(max(...)) formulation makes it hard to solve this problem analytically, which is why scipy.optimize fits well.
The solution is based on the mathematical formulation for distance between a point and a finite line segment outlined in https://math.stackexchange.com/questions/330269/the-distance-from-a-point-to-a-line-segment
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import minimize, NonlinearConstraint
def calc_distance_from_point_set(v_):
#v_ is accepted as 1d array to make easier with scipy.optimize
#Reshape into two points
v = (v_[:2].reshape(2, 1), v_[2:].reshape(2, 1))
#Calculate t* for s(t*) = v_0 + t*(v_1-v_0), for the line segment w.r.t each point
t_star_matrix = np.minimum(np.maximum(np.matmul(P-v[0].T, v[1]-v[0]) / np.linalg.norm(v[1]-v[0])**2, 0), 1)
#Calculate s(t*)
s_t_star_matrix = v[0]+((t_star_matrix.ravel())*(v[1]-v[0]))
#Take distance between all points and respective point on segment
distance_from_every_point = np.linalg.norm(P.T -s_t_star_matrix, axis=0)
return np.sum(distance_from_every_point)
if __name__ == '__main__':
#Random points from bounding box
box_1 = np.random.uniform(-5, 5, 20)
box_2 = np.random.uniform(-5, 5, 20)
P = np.stack([box_1, box_2], axis=1)
segment_length = 3
segment_length_constraint = NonlinearConstraint(fun=lambda x: np.linalg.norm(np.array([x[0], x[1]]) - np.array([x[2] ,x[3]])), lb=[segment_length], ub=[segment_length])
point = minimize(calc_distance_from_point_set, (0.0,-.0,1.0,1.0), options={'maxiter': 100, 'disp': True},constraints=segment_length_constraint).x
plt.scatter(box_1, box_2)
plt.plot([point[0], point[2]], [point[1], point[3]])
Example result:
Here is a proposition in python. The distance between the points and the line is computed based on the approach proposed here: Fit a line segment to a set of points
The fact that the segment has a finite length, which impose the usage of min and max function, or if tests to see whether we have to use perpendicular distance or distance to one of the end points, makes really difficult (impossible?) to get an analytic solution.
The proposed solution will thus use optimization algorithm to approach the best solution. It uses scipy.optimize.minimize, see: https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.minimize.html
Since the segment length is fixed, we have only three degrees of freedom. In the proposed solution I use x and y coordinate of the starting segment point and segment slope as free parameters. I use getCoordinates function to get starting and ending point of the segment from these 3 parameters and the length.
import numpy as np
from scipy.optimize import minimize
import matplotlib.pyplot as plt
import math as m
from scipy.spatial import distance
# Plot the points and the segment
def plotFunction(points,x1,x2):
'Plotting function for plane and iterations'
plt.plot(points[:,0],points[:,1],'ro')
plt.plot([x1[0],x2[0]],[x1[1],x2[1]])
plt.xlim(0, 1)
plt.ylim(0, 1)
plt.show()
# Get the sum of the distance between all the points and the segment
# The segment is defined by guess and length were:
# guess[0]=x coordinate of the starting point
# guess[1]=y coordinate of the starting point
# guess[2]=slope
# Since distance is always >0 no need to use root mean square values
def getDist(guess,points,length):
start_pt=np.array([guess[0],guess[1]])
slope=guess[2]
[x1,x2]=getCoordinates(start_pt,slope,length)
total_dist=0
# Loop over each points to get the distance between the point and the segment
for pt in points:
total_dist+=minimum_distance(x1,x2,pt,length)
return(total_dist)
# Return minimum distance between line segment x1-x2 and point pt
# Adapted from https://stackoverflow.com/questions/849211/shortest-distance-between-a-point-and-a-line-segment
def minimum_distance(x1, x2, pt,length):
length2 = length**2 # i.e. |x1-x2|^2 - avoid a sqrt, we use length that we already know to avoid re-computation
if length2 == 0.0:
return distance.euclidean(p, v);
# Consider the line extending the segment, parameterized as x1 + t (x2 - x1).
# We find projection of point p onto the line.
# It falls where t = [(pt-x1) . (x2-x1)] / |x2-x1|^2
# We clamp t from [0,1] to handle points outside the segment vw.
t = max(0, min(1, np.dot(pt - x1, x2 - x1) / length2));
projection = x1 + t * (x2 - x1); # Projection falls on the segment
return distance.euclidean(pt, projection);
# Get coordinates of start and end point of the segment from start_pt,
# slope and length, obtained by solving slope=dy/dx, dx^2+dy^2=length
def getCoordinates(start_pt,slope,length):
x1=start_pt
dx=length/m.sqrt(slope**2+1)
dy=slope*dx
x2=start_pt+np.array([dx,dy])
return [x1,x2]
if __name__ == '__main__':
# Generate random points
num_points=20
points=np.random.rand(num_points,2)
# Starting position
length=0.5
start_pt=np.array([0.25,0.5])
slope=0
#Use scipy.optimize, minimize to find the best start_pt and slope combination
res = minimize(getDist, x0=[start_pt[0],start_pt[1],slope], args=(points,length), method="Nelder-Mead")
# Retreive best parameters
start_pt=np.array([res.x[0],res.x[1]])
slope=res.x[2]
[x1,x2]=getCoordinates(start_pt,slope,length)
print("\n** The best segment found is defined by:")
print("\t** start_pt:\t",x1)
print("\t** end_pt:\t",x2)
print("\t** slope:\t",slope)
print("** The total distance is:",getDist([x1[0],x2[1],slope],points,length),"\n")
# Plot results
plotFunction(points,x1,x2)
First of all, will appreciate if someone will give me a proper term for "annulus with a shifted hole", see exactly what kind of shape I mean on a picture below.
Back to main question: I want to pick a random point in the orange area, uniform distribution is not required. For a case of a usual annulus I would've picked random point in (r:R) range and a random angle, then transform those to x,y and it's done. But for this unusual shape... is there even a "simple" formula for that, or should I approach it by doing some kind of polygonal approximation of a shape?
I'm interested in a general approach but will appreciate an example in python, javascript or any coding language of your choice.
Here's a simple method that gives a uniform distribution with no resampling.
For simplicity assume that the center of the outer boundary circle (radius r_outer) is at (0, 0) and that the center of the inner circular boundary (radius r_inner) lies at (x_inner, y_inner).
Write D for the outer disk, H1 for the subset of the plane given by the off-center inner hole, and H2 for the central disk of radius r_inner, centered at (0, 0).
Now suppose that we ignore the fact that the inner circle is not central, and instead of sampling from D-H1 we sample from D-H2 (which is easy to do uniformly). Then we've made two mistakes:
there's a region A = H1 - H2 that we might sample from, even though those samples shouldn't be in the result.
there's a region B = H2 - H1 that we never sample from, even though we should
But here's the thing: the regions A and B are congruent: given any point (x, y) in the plane, (x, y) is in H2 if and only if (x_inner - x, y_inner - y) is in H1, and it follows that (x, y) is in A if and only if (x_inner - x, y_inner - y) is in B! The map (x, y) -> (x_inner - x, y_inner - y) represents a rotation by 180 degress around the point (0.5*x_inner, 0.5*y_inner). So there's a simple trick: generate from D - H2, and if we end up with something in H1 - H2, rotate to get the corresponding point of H2 - H1 instead.
Here's the code. Note the use of the square root of a uniform distribution to choose the radius: this is a standard trick. See this article, for example.
import math
import random
def sample(r_outer, r_inner, x_inner, y_inner):
"""
Sample uniformly from (x, y) satisfiying:
x**2 + y**2 <= r_outer**2
(x-x_inner)**2 + (y-y_inner)**2 > r_inner**2
Assumes that the inner circle lies inside the outer circle;
i.e., that hypot(x_inner, y_inner) <= r_outer - r_inner.
"""
# Sample from a normal annulus with radii r_inner and r_outer.
rad = math.sqrt(random.uniform(r_inner**2, r_outer**2))
angle = random.uniform(-math.pi, math.pi)
x, y = rad*math.cos(angle),rad*math.sin(angle)
# If we're inside the forbidden hole, reflect.
if math.hypot(x - x_inner, y - y_inner) < r_inner:
x, y = x_inner - x, y_inner - y
return x, y
And an example plot, generated by the following:
import matplotlib.pyplot as plt
samples = [sample(5, 2, 1.0, 2.0) for _ in range(10000)]
xs, ys = zip(*samples)
plt.scatter(xs, ys, s=0.1)
plt.axis("equal")
plt.show()
Do you really need exact sampling? Because with acceptance/rejection it should work just fine. I assume big orange circle is located at (0,0)
import math
import random
def sample_2_circles(xr, yr, r, R):
"""
R - big radius
r, xr, yr - small radius and its position
"""
x = xr
y = yr
cnd = True
while cnd:
# sample uniformly in whole orange circle
phi = 2.0 * math.pi * random.random()
rad = R * math.sqrt(random.random())
x = rad * math.cos(phi)
y = rad * math.sin(phi)
# check condition - if True we continue in the loop with sampling
cnd = ( (x-xr)**2 + (y-yr)**2 < r*r )
return (x,y)
Since you have shown no equation, algorithm, or code of your own, but just an outline of an algorithm for center-aligned circles, I'll also just give the outline of an algorithm here for the more general case.
The smaller circle is the image of the larger circle under a similarity transformation. I.e. there is a fixed point in the larger circle and a ratio (which is R/r, greater than one) such that you can take any point on the smaller circle, examine the vector from the fixed point to that point, and multiply that vector by the ratio, then the end of that vector when it starts from the fixed point is a point on the larger circle. This transformation is one-to-one.
So you can choose a random point on the smaller circle (choose the angle at random between 0 and two-pi) and choose a ratio at random between 1 and the proportionality ratio R/r between the circles. Then use that the similarity transformation with the same fixed point but using the random ratio to get the image point of the just-chosen point on the smaller circle. This is a random point in your desired region.
This method is fairly simple. In fact, the hardest mathematical part is finding the fixed point of the similarity transformation. But this is pretty easy, given the centers and radii of the two circles. Hint: the transformation takes the center of the smaller circle to the center of the larger circle.
Ask if you need more detail. My algorithm does not yield a uniform distribution: the points will be more tightly packed where the circles are closest together and less tightly packed where the circles are farthest apart.
Here is some untested Python 3.6.2 code that does the above. I'll test it and show a graphic for it when I can.
import math
import random
def rand_pt_between_circles(x_inner,
y_inner,
r_inner,
x_outer,
y_outer,
r_outer):
"""Return a random floating-point 2D point located between the
inner and the outer circles given by their center coordinates and
radii. No error checking is done on the parameters."""
# Find the fixed point of the similarity transformation from the
# inner circle to the outer circle.
x_fixed = x_inner - (x_outer - x_inner) / (r_outer - r_inner) * r_inner
y_fixed = y_inner - (y_outer - y_inner) / (r_outer - r_inner) * r_inner
# Find a a random transformation ratio between 1 and r_outer / r_inner
# and a random point on the inner circle
ratio = 1 + (r_outer - r_inner) * random.random()
theta = 2 * math.pi * random.random()
x_start = x_inner + r_inner * math.cos(theta)
y_start = y_inner + r_inner * math.sin(theta)
# Apply the similarity transformation to the random point.
x_result = x_fixed + (x_start - x_fixed) * ratio
y_result = y_fixed + (y_start - y_fixed) * ratio
return x_result, y_result
The acceptance/rejection method as described by Severin Pappadeux is probably the simplest.
For a direct approach, you can also work in polar coordinates, with the center of the hole as the pole.
The polar equation (Θ, σ) (sorry, no rho) of the external circle will be
(σ cosΘ - xc)² + (σ sinΘ - yc)² = σ² - 2(cosΘ xc + sinΘ yc)σ + xc² + yc² = R²
This is a quadratic equation in σ, that you can easily solve in terms of Θ. Then you can draw an angle in 0, 2π an draw a radius between r and σ.
This won't give you a uniform distribution, because the range of σ is a function of Θ and because of the polar bias. This might be fixed by computing a suitable transfer function, but this is a little technical and probably not tractable analytically.
I'm working on straightening splines as a component of my larger project to straighten curved text.
After fitting a spline to my data points, I use scipy's splev to get the derivative of the spline at each point along the curve. Since the derivative gives me the slope of the tangent to the curve at a given point (unless I'm very confused), I determine the rotation needed to produce a straight line by comparing the derivative to a line with 0 slope.
Having established the rotation needed at each point to straighten my spline, I loop over each point and apply the corrective rotation to the current point and each preceding point.
The relevant code follows:
import numpy as np
from numpy import arange
from scipy import interpolate
import matplotlib.pyplot as plt
import math
import random
def rotate(origin, point, angle):
ox, oy = origin
px, py = point
qx = ox + math.cos(angle) * (px - ox) - math.sin(angle) * (py - oy)
qy = oy + math.sin(angle) * (px - ox) + math.cos(angle) * (py - oy)
return qx, qy
xxx = [0,2,4,4,2,0]
yyy = [0,2,4,6,8,10]
tckp, u = interpolate.splprep([xxx, yyy], s=3, k=2, nest=-1)
xpointsnew, ypointsnew = interpolate.splev(u, tckp)
dx, dy = interpolate.splev(u, tckp, der=1)
fullder = dy/dx
rotating_x = xxx
rotating_y = yyy
index = -1
for i in fullder:
index += 1
corrective_rotation = -(math.degrees(math.atan(0)-math.atan(fullder[index])))
print(corrective_rotation)
rotation_center = [rotating_x[index], rotating_y[index]]
target_indices = np.arange(0,index,1)
for i in target_indices:
rotation_target = [rotating_x[i], rotating_y[i]]
qx, qy = rotate(rotation_target,rotation_center,math.radians(corrective_rotation))
rotating_x[i] = qx
rotating_y[i] = qy
print(rotating_x)
print(rotating_y)
plt.plot(xpointsnew, ypointsnew, 'r-')
plt.plot(rotating_x, rotating_y, 'b-')
plt.show()
What I'm doing isn't working, but I'm not sure why. Not only is the resulting line not straight, it's also much shorter than the original curve. Is the approach outlined above fundamentally flawed in some way? Am I doing something stupid in my code? I would really appreciate a second pair of eyes.
A fundamental flaw of the algorithm is that it takes slope at a point as the amount of necessary rotation of one of two segments in which that point divides the curve. As an example, consider a straight line at 60 degrees. Your algorithm will produce rotation of 60 degrees at every knot of the line, in effect making them all 120-degree angles.
You are not rotating the entire curve, only a part of it (up to index in your version; after i in my version). The appropriate amount of rotation is how sharply the curve turns at that point, which is reflected by the change of its slope — not the slope itself.
Then there are minor details like
incorrect order of rotation_center and rotation_target in the list of arguments;
pointless conversion to degrees and back;
using atan(dy/dx) where atan2(dy, dx) should be used;
and the strange decision to rotate from the end of the curve.
Here is my version; the only changes are in the for loop.
for i in range(len(xxx)-1):
corrective_rotation = -(math.atan2(dy[i+1], dx[i+1]) - math.atan2(dy[i], dx[i]))
print(corrective_rotation)
rotation_center = [rotating_x[i], rotating_y[i]]
for k in range(i+1, len(xxx)):
rotation_target = [rotating_x[k], rotating_y[k]]
qx, qy = rotate(rotation_center, rotation_target, corrective_rotation)
rotating_x[k] = qx
rotating_y[k] = qy
By the way, plt.axes().set_aspect('equal') helps avoid the illusion that the curve changed length after rotation.
Finally, I should say that taking angles from the point values of the derivative of an interpolating spline is a very questionable decision. Finite differences at an appropriate scale are more robust.
Suppose you know the three vertices for a spherical triangle.
Then how do you draw the sides on a sphere in 3D?
I need some python code to use in Blender 3d modelisation software.
I already have the sphere done in 3D in Blender.
Thanks & happy blendering.
note 1:
i have the 3 points / vertices (p1,p2,p3 ) on the sphere for a spherical triangle
but i need to trace the edges on the sphere in 3D
so what would be the equations needed to determine all vertices between each points pair of the triangle on the sphere
3 edges from p1 to p2 - p2 to p3 and o3 to p1
i know it has something to do with the Great circle for Geodesic on a sphere
but cannot find the proper equations to do the calculations in spherical coordinates!
Thanks
Great circles
it would have been interesting to see a solution with great circle and see tehsolution in spherical coordinates directly !
but still interesting to do it in the euclidiens space
Thanks
ok i used this idea of line segment between 2 points
but did not do it as indicated before
i used an alternative method - Bezier line interpolation**
i parametrize the line with a bezier line
then subdivided and calculated as shonw ealier the ratio and angle for each of the subdivided bezier point on the chord
and it works very well and very precise
but it would be interesting to see how it is done whit the earlier method
but not certain how to do the iteration loop?
how do you load up the python code here
just past it with Ctrl-V?
Thanks and happy 2.5
i do use the blenders' forum
but no guaranti to get a clear answer all the time!
that's why i tried here - took a chance
i did the first edge seems to work
now got to make a loop to get multi segment for first edge and then do the other edges also
2- other subject
i open here a post on bezier triangle patch
i know it's not a usfull tool
but just to show how it is done
have youeseen a python sript to do theses triangel patch
and i did ask this questin on blender's foum and no answer
also on IRC python and sems to be dead right now
probably guys are too busy finishing the 2.5 Beta vesion which should come out in a week or 2
Hey Thanks a lot for this math discussion
if i have problem be back tomorrow
happy math and 2.5
Create Sine Mesh
Python code to create a sine wave mesh in Blender:
import math
import Blender
from Blender import NMesh
x = -1 * math.pi
mesh = NMesh.GetRaw()
vNew = NMesh.Vert( x, math.sin( x ), 0 )
mesh.verts.append( vNew )
while x < math.pi:
x += 0.1
vOld = vNew
vNew = NMesh.Vert( x, math.sin( x ), 0 )
mesh.verts.append( vNew )
mesh.addEdge( vOld, vNew )
NMesh.PutRaw( mesh, "SineWave", 1 )
Blender.Redraw()
The code's explanation is at: http://davidjarvis.ca/blender/tutorial-04.shtml
Algorithm to Plot Edges
Drawing one line segment is the same as drawing three, so the problem can be restated as:
How do you draw an arc on a sphere,
given two end points?
In other words, draw an arc between the following two points on a sphere:
P1 = (x1, y1, z1)
P2 = (x2, y2, z2)
Solve this by plotting many mid-points along the arc P1P2 as follows:
Calculate the radius of the sphere:
R = sqrt( x12 + y12 + z12 )
Calculate the mid-point (m) of the line between P1 and P2:
Pm = (xm, ym, zm)
xm = (x1 + x2) / 2
ym = (y1 + y2) / 2
zm = (z1 + z2) / 2
Calculate the length to the mid-point of the line between P1 and P2:
Lm = sqrt( xm2, ym2, zm2 )
Calculate the ratio of the sphere's radius to the length of the mid-point:
k = R / Lm
Calculate the mid-point along the arc:
Am = k * Pm = (k * xm, k * ym, k * zm)
For P1 to P2, create two edges:
P1 to Am
Am to P2
The two edges will cut through the sphere. To solve this, calculate the mid-points between P1Am and AmP2. The more mid-points, the more closely the line segments will follow the sphere's surface.
As Blender is rather precise with its calculations, the resulting arc will likely be (asymptotically) hidden by the sphere. Once you have created the triangular mesh, move it away from the sphere by a few units (like 0.01 or so).
Use a Spline
Another solution is to create a spline from the following:
sphere's radius (calculated as above)
P1
Am
P2
The resulting splines must be moved in front of the sphere.
Blender Artists Forums
The Blender experts will also have great ideas on how to solve this; try asking them.
See Also
http://www.mathnews.uwaterloo.ca/Issues/mn11106/DotProduct.php
http://cr4.globalspec.com/thread/27311/Urgent-Midpoint-of-Arc-formula
One cheap and easy method for doing this would be to create the triangle and subdivide the faces down to the level of detail you want, then normalize all the vertices to the radius you want.