I think, there is no perfect solution to this problem, though:
What is the problem:
- Chords of each circle need to be regular in both directions (latitude, longitude)
- But this chords length need to correspond to a latitude of this sphere
- And this latitude may not correspond to an entire amount of the chord length
So the result is only an approximation.
The code without the UI:
import bpy
from math import pi, cos, sin
#Create a new mesh from a geometry
def CreateMesh( scene, name, location, vertices, edges, polygons ):
mesh = bpy.data.meshes.new( name )
obj = bpy.data.objects.new( name, mesh )
obj.location = location
scene.objects.link( obj )
scene.objects.active = obj
obj.select = True
mesh.from_pydata( vertices, edges, polygons )
mesh.update()
return obj
#Merge new vertices (a ring) to previous one
def MergeGeometry( vertices, edges, newVertices ):
base = len( vertices )
vertices += newVertices
newVerticesAmount = len( newVertices )
if newVerticesAmount > 2:
edges += [(base + i, base + int((i+1) % newVerticesAmount) ) for i in range( newVerticesAmount )]
elif newVerticesAmount == 2:
edges += [(base, base + 1)]
return vertices, edges
#Calculate a circle
def Circle( z, r, verticesAmount ):
baseAngle = 2 * pi / verticesAmount
return [(r * cos(i * baseAngle), r * sin(i * baseAngle), z) for i in range( verticesAmount )]
#Calculate the sphere
def HomogeneousSphereBySegments( segments, r ):
vertices, edges = [], []
if segments % 2 == 0:
ringAmount = segments // 2
baseAngle = pi / ringAmount
chord = 2 * r * sin( pi / segments )
arc = 2 * pi * r / segments
else:
#If odd we have to shift the angle from the 'equator'
ringAmount = segments // 2
baseAngle = pi / ringAmount
chord = 2 * r * cos( baseAngle / 2 ) * sin( pi / segments )
arc = 2 * pi * r * cos( baseAngle / 2 ) / segments
#First pole
vertices += [(0,0,-r)]
for i in range( 1, ringAmount ):
angle = (i * baseAngle) - (pi / 2)
z = r * sin( angle )
localR = abs( r * cos( angle ) )
verticesAmount = int( 2 * pi * localR / arc )
vertices, edges = MergeGeometry( vertices, edges, Circle( z, localR, verticesAmount ) )
print( ringAmount, baseAngle, angle, z, localR )
#Second pole
vertices += [(0,0,r)]
return vertices, edges
Blend file with code usable as an operator (add mesh, 'Homogeneous Sphere'):